Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Updating an array element

  arr[3] = 'New content';
Updating an array element immutably

  arr = arr.map((element, index) => {
    if (index === 3) return 'New content';
    return element;
  });
It's possible, sure, but it feels terrible. JavaScript objects want to be mutated - it's the most idiomatic way of interacting with them. Whether functional programming paradigm is good (I certainly feel it is) is beside the point - JS wasn't designed for it.

When I think of immutable primitives, I think of Python's tuples, which will raise a big fat error when you try to mutate them, or even better, Swift's structs, which gives you a new copy with every mutation.



I know your point wasn't strictly pertaining to boilerplate, but for an apples-to-apples comparison, the most succinct way to change a member of an array immutably would be something like:

  arr = arr.map((e,i) => i === 3 ? 'new content' : e)
That said, idiomatic or not, functional patterns in JS are a boon for debugging (especially with Redux devtools & time travel). To your example, even if mutability is more succinct, using map() lets me chain all sorts of methods together without storing intermediate values in vars.

Between the spread operator (...), immutable array methods (slice, reduce, map, filter, and even sort if preceded by .slice()), immutability in native JS ain't half bad.


I've created library `transmutable` for performing automatic copy-on-write behavior in JS (you just write imperative code which is transformed behind scenes into immutable updates https://npmjs.com/package/transmutable

This can avoid boilerplate traditionally associated with immutable updates in JavaScript, because you just write

    const copy = transform(original, stage => {
       stage.someArray[index] = 42;
    });
and it returns immutable copy of original object with appropriate mutations.


    (set arr 3 "New content")

    (set-in
      deeply-nested
      [arbitraty path to the element]
      "New content")
convenient updates of immutable datastructures are possible.


if you use ES2015:

  arr = [
    ...arr.slice(0, 2),
    'New Content',
    ...arr.slice(3)
  ]


In my eyes this slice of code is even worse than the array map one, where there is 2.5 pieces of logic (map, if, and 2 return that makes for the .5).

In the version you have 2 spread operators, an array construct and 3 hardcoded ints.

I might not use the correct academic terms, and I might not be yet fully accustomed to es2015, but this way of writing stuff always make me pause and double check the code.


In ES2017 this gets substantially better:

const arr2 = Object.values({...arr, 3: 'New Content'});




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: