DEV Community

Discussion on: Immutability in JavaScript

Collapse
 
stevenlangbroek profile image
Steven Langbroek

I gotta say, data-first & lack of auto-currying really hurts their API. Consider:

const person = {
  name: 'Steven'
  cities: ['Berlin', 'Lisbon'],
  currentCity: 'Berlin'
}

If I want to change my current city, as well as push a new one onto the list of cities, I have to do this:

const withNewCity = concat(person, 'cities', 'Amsterdam');
const movedIntoNewCity = set(person, 'currentCity', 'Amsterdam');

Nothing here is reusable or composable. If the methods had taken their data last, and have been curried, we could've had both:

const movedIntoNewCity = compose(
  concat('cities', 'Amsterdam'),
  set('currentCity', 'Amsterdam')
)(person);

Which could be abstract out into:

const moveToNewCity = newCity => compose(
  concat('cities', newCity),
  set('currentCity', newCity)
)

const movedPerson = moveToNewCity('Amsterdam')(person)
Collapse
 
stevenlangbroek profile image
Steven Langbroek

Good API inspiration, monocle-ts: github.com/gcanti/monocle-ts

const name = Lens.fromPath<Employee>()(['company', 'address', 'street', 'name'])

name.modify(capitalize)(employee)
Collapse
 
nlepage profile image
Nicolas Lepage

Hi Steven!

Actually our API has a way to do this:

const { flow, set, push } = require('immutadot')

const person = {
  name: 'Steven',
  cities: ['Berlin', 'Lisbon'],
  currentCity: 'Berlin'
}

const movedIntoNewCity = flow(
  push('cities', 'Amsterdam'),
  set('currentCity', 'Amsterdam')
)(person);

console.log(movedIntoNewCity)

Here's your working example on runkit: runkit.com/embed/kr9e9tins87j

Anyway thank you for your comment, we're waiting for other constructive feedback from you.

Collapse
 
stevenlangbroek profile image
Steven Langbroek • Edited

That's great! Took a cursory look at the code, and if you'd reversed the argument order, you could've delegated to pipe (maybe a more familiar name for people?) and compose (right-associative version of pipe) from lodash, ramda or whatever. The problem now is, what if I'm already piping a bunch of unary functions using any of the bigger FP toolbelts, and add a immutadot function? It won't work:

const newState = pipe(
  over('items', filter(has('id')),
  // won't work
  push('items', newItem)
)(oldState);