rtfeldman / seamless-immutable

Immutable data structures for JavaScript which are backwards-compatible with normal JS Arrays and Objects.
BSD 3-Clause "New" or "Revised" License
5.37k stars 195 forks source link

What is that best practice for making many deep changes in an immutable object? #122

Open robclouth opened 8 years ago

robclouth commented 8 years ago

Which is best practice out of these options (performance and style)?

  1. Make the object immutable (deep), make all the changes, merge back into the original mutable object
  2. Call setIn multiple times into the same reference
  3. Build up an array of objects for a deep merge()

Thanks

ericclemmons commented 8 years ago

I'm curious about this as well. It just came up as we were looking to leverage this project within our Redux reducers.

jbmeslin commented 8 years ago

today, i do something like this:

//reducer.js

       return state.merge({
            nestedObject: utils.updateNested(state.nestedObject, state.index, action.val),
            otherVal: {}

        });

//utils.js

    static updateNested(nestedObject, index, val) {
        return nestedObject.updateIn(['list', index], (item) => {

        return item.merge({
            attr1: val.,
            att2: undefined  // or other props in val     
        });

    });
}
ericclemmons commented 8 years ago

I wish dot-delimited keys worked to have something like this:

state.deepMerge({
  "attr1": val,
  "attr2": undefined,
  "some.deep.attr": { otherVal },
  "some.other.deep": "awwww snap!",
});

That's what I dig about selectn, but that's just a selector lib.

jeffbski commented 8 years ago

Maybe something like immutable.js's withMutations() would be a nice addition to the api for this?

jbmeslin commented 8 years ago

The withMutations function is used when we need to update a tree with a loop ? All changes are done first in a mutable object and at the end apply on the initial object ? I think if we can have a deepMerge function which one do something like withMutations it will be great.

I say that because in a large team, in a large application, some dev are not (javascript) expert and making the choice to use a withMutations or not can be tricky.

krzysztofpniak commented 7 years ago

@jeffbski the origin of immutable data structures is in functional programming paradigm. The whole thing is about not writing mutable code. You can check good functional languages like haskell, inside them there are no things like mutable structures.

In my opinion multiple setIn / updateIn is the way to go, but the users of the library and its author should be sure that this way is implemented with best performance as it can be(or close to this ;) ).

Side note: seamless-immutable adds its functionality as instance methods. More functional way is to have it as static functions in module scope. Good place to have a look is lodash/fp. That way it could look like: const modifyX = flowRight([ setIn(['a, 'b'], 1), setIn([['c', 'd'], 2]) ]); const newState = modifyX(oldState);