
Immutable Data Collections for Javascript - gagan2020
https://github.com/facebook/immutable-js
======
leebyron
Hey, I'm the author of this library. It's definitely inspired by mori (and
clojure and Haskell) and the reason I ended up building something different
was to present a more JavaScript friendly API (and academically, to learn
about HAMT). I've built this over the last couple weeks, and we are not using
it internally yet - but I wanted to ensure development of it happened in
public.

~~~
fnordsensei
A question: how influential has Swanodette's work with ClojureScript/Om in
relation to React been to the direction that you (yourself and Facebook) are
taking the evolution of React and its supporting libraries in?

From what I've seen, I'm guessing: quite a bit, but I'm not sure that I've
noticed it being mentioned. In particular, I'm guessing that the performance
characteristics of Om might be especially inspiring.

Edit: Oh, and good work on the library! It's great to see efforts to make the
case of immutability within the world of JS.

~~~
chenglou
I contribute to React. I'm definitely a big fan of ClojureScript and I borrow
ideas from it when I can. I currently have a few crazy ideas that are direct
results of looking into the Clojure (or Haskell) ecosystem and finding that
they've solved my problems, but better. In general, some of the problems we
face, at language/library/ecosystem level, might simply not exist in these
languages. It's a shame they're not more popular.

Regarding popularity, I feel that sometimes the web development community can
be ironically dogmatic, considering that it's a free and open platform (see:
HN/Reddit's initial reaction to React). Looking back, I still find it
incredible that React actually gained so much traction when it defies so many
of the pre-established "best practices". I think lots of people, including me,
are learning more and more to take a step back before dismissing an idea.

So if you were one of those that dismissed Clojure/ClojureScript because
"parentheses in front of my function call?", "snake case isn't for me", or
"it's too different from idiomatic js" (I hope this one isn't too much of a
strawman here), then I urge you to give it another try. Learning React doesn't
have to be the only time you open your mind to new ideas and reconsider best
practices.

~~~
KurtMueller
Would you mind espousing a bit on what problems we currently face that might
not exist in functional languages like Clojure/Haskell?

Also, I just started getting into ClojureScript in order to learn Om. I would
love to know your thoughts on why it's worth it to learn Clojure/Haskell.

~~~
chenglou
I don't want to go further into a language/library/ecosystem war here. Glad to
talk more about it on #reactjs though =).

------
falava
There is also Mori[1], a JavaScript API for using ClojureScript's persistent
data structures:

    
    
      [1] http://swannodette.github.io/mori/

~~~
smrtinsert
Mori also provides clojure like functionality for the new collections greatly
simplifying how you would use them - if you don't use Clojure you might think
of the additional functions as an underscore for immutable collections.

I don't see a reason to use any other immutable js lib when Mori exists.

~~~
misuba
Mori's a bit impractical for use in the browser due to its size.

~~~
taude
I'm not seeing how a 32 KB download is impractical in browser use do to size
(assuming the above statement about 32KB is true). Is there something else to
it?

~~~
misuba
I didn't see any such statement above. From 176K to 37K (that's what I got on
my console anyway) is impressive.

------
abaco
Bit confused (ignorant actually) here. Can someone give a 'real world' example
of the benefits of immutabile objects in js?

~~~
friesenj
The first time I understood why immutable objects are important was in this
podcast with ClojureScript and Mori author David Nolan:
[http://podcasts.thoughtbot.com/giantrobots/93](http://podcasts.thoughtbot.com/giantrobots/93)

What I thought was the key point was this:

Let's say you have a regular JS array. There is a reference to it in memory
and it has a certain value. Now you change an element in that array. You've
just mutated it. In JS, the reference in memory doesn't change, but now the
value of what it's pointing to has. So in order to know if the value has
changed, you need to do a comparison on every element on that array, which is
expensive.

Now let's say you have a immutable array (such as from the Immutable FB
library or Mori). If you change an element in that array, you get a new array
and a new array reference in memory. In other words, if you check that the
reference in memory is the same, you are guaranteed that the value is the same
(in this case, the array). So checking for equality is fast and cheap because
you are only checking the reference, not each value in the array.

One way this is important in React is that now if your component state (or
entire app state) is represented by an immutable data structure, you can just
check for reference equality in the shouldComponentUpdate() method when
deciding to re-render that component. If the reference is equal, you are
guaranteed that the data backing that component hasn't changed and you can
return false, telling React not to re-render.

What's surprising is that people have made these data structures also very
memory efficient. You can see David Nolan talking about how they work and
memory comparisons here:
[https://www.youtube.com/watch?v=mS264h8KGwk](https://www.youtube.com/watch?v=mS264h8KGwk)

~~~
nawitus
Note that you can have cheap equality detection by using e.g. flags or
revision counters and so on (but there are limits due to JavaScript's
nature..). The problem is that JavaScript currently doesn't support this
properly out of the box, but Object.observe is coming in the next standard.

I personally like the safety benefits of immutability. You can give objects to
functions and not worry about the functions changing the object. The only way
to guarantee that otherwise is to clone the object, but that takes quite a bit
of performance.

~~~
Touche
Isn't this library probably cloning?

~~~
rojoca
If you watch the linked video above you will see how clever persistent data
structures mean that nothing is ever cloned or copied.

~~~
bsimpson
Good to know. I never got into immutable collections because I presumed they
would result in things being allocated all the time (and that that would be
expensive).

------
dreamdu5t
The original npm package "immutable" was
[https://github.com/hughfdjackson/immutable](https://github.com/hughfdjackson/immutable)
(npm install immutable@1.4)

Did Facebook buy the npm name from hughfdjackson, did he give it to them, or
did NPM switch ownership?

~~~
augustl
There's an acknowledgement in the README.

[https://github.com/facebook/immutable-
js/blob/fdc4005fe30286...](https://github.com/facebook/immutable-
js/blob/fdc4005fe302866626ab94e060bc06b8381a94be/README.md)

------
vineet
Sounds like more of the pieces of React/Flux are being opensourced. :-)

Interesting to see references to TypeScript. Is it prevalent at FB?

~~~
wukkuan
This isn't used internally by Facebook at this point. The author mentioned
this after your post.
[https://news.ycombinator.com/item?id=8108741](https://news.ycombinator.com/item?id=8108741)

~~~
vineet
Thanks!

But even if it is not being used yet - do we know if Facebook uses Typescript
(or some extension of it)?

------
ScottBurson
If anyone is interested in functional collections for Common Lisp or Java,
have a look at FSet:
[http://www.ergy.com/FSet.html](http://www.ergy.com/FSet.html)

------
derengel
So you can use the Clojurescript/Om/Reagent/React model without Clojurescript,
nice for people who don't want or can't jump into Clojurescript right now.

------
jannes
I wish the README would tell us a little bit more about how to use it in
conjunction with React. Especially the logic for shouldComponentUpdate() would
be interesting.

~~~
EdwardMSmith
From my understanding, it makes shouldComponentUpdate() very simple:

return nextProps.value !== this.props.value;

If the object is different, it has changed.

~~~
jannes
Yes, that's how for I've got, too. But then you have a problem if your React
component has multiple attributes. Suddenly your check beckomes much larger:

    
    
      return (nextProps.attr1 !== this.props.attr1 ||
              nextProps.attr2 !== this.props.attr2 ||
              nextProps.attr3 !== this.props.attr3 ||
              nextProps.attr4 !== this.props.attr4);
    

Which would result in a lot of boilerplate code if you had to do this for
every single attribute in every component in your application. It would be
much simpler to just do this check:

    
    
      return nextProps !== this.props;
    

But that's impossible if you're using JSX, because the JSX compiler
automatically inserts a normal JavaScript object into your code, instead of an
immutable object from this library.

So from my point of view this immutable-js library and JSX seem incompatible,
which is kind of weird since Facebook apparently uses JSX internally for their
React code.

~~~
vjeux
PureRenderMixin[1] is doing this without having you to enumerate all the props

[1] [http://facebook.github.io/react/docs/pure-render-
mixin.html](http://facebook.github.io/react/docs/pure-render-mixin.html)

------
Kiro
I don't understand this whole immutable thing... Why not just avoid changing
the data once created? Why do you need a library?

~~~
_halgari
Not good enough. When the time comes that you do need to add something, then
what? Clone it? In languages that allow you to freeze a collection, adding
something to a frozen collection is often a O(n) operation. Most of the
collections in this library provide operations that grow collections in
(almost) constant time.

~~~
Kiro
> Clone it?

Yes, isn't that enough?

~~~
afandian
Let's say you want to create a set by recursing along a million long sequence,
collecting the unique values. This would be done with an operation called
`reduce`.

The time and storage complexity of that would be exponential if each step you
had to clone a copy of the output list. With a persistent data structure, as
much of the structure as possible is re-used.

And a list is the simplest possible structure. What about a tree?

Using `reduce` is, I would say, in the top 5 techniques used in functional
programming. And it would be severely hobbled without efficient persistent
immutable structures.

------
Strilanc
I have to admit, I find it odd that we name immutable data structures based on
what they don't do instead of what they do.

Of course, what they do is _efficient persistence_. You want a snapshot of the
data? You want a non-volatile reference? You've already got one! _That 's_ the
feature. They should be called persistent data structures.

~~~
TheLoneWolfling
You can have an efficiently persistent data structure that isn't immutable.

For example, a rope that reorganizes internal nodes to maximize structure
sharing.

------
colinramsay
React's documentation also discuss their immutability helpers [1]. This new
library looks like a better way of implementing this though. Will the
documentation be amended to discuss use of immutable-js?

[1]
[http://facebook.github.io/react/docs/update.html](http://facebook.github.io/react/docs/update.html)

~~~
vjeux
React immutability helpers pros:

\- Work on regular JavaScript Object and Array so it's easy to get started and
integrate to your app

\- You don't need to wrap objects inside of Immutable to use it and you can
use `obj.key` and `arr[0]` syntax for accessing them instead of
`obj.get('key')` and `arr.get(0)`

cons:

\- There are no safe-guards if you mutate the objects and it'll likely break
your app in subtle ways. This kind of discipline is very hard to get in big
projects

\- You are stuck with primitive data structures (instead of map hash trie), so
it's not going to be as performant and memory efficient.

------
33a
Also relevant (and not included in this collection) is the following
functional red-black tree implementation:

[https://github.com/mikolalysenko/functional-red-black-
tree](https://github.com/mikolalysenko/functional-red-black-tree)

------
collyw
Can someone give me a good example of where immutable data structures are
better than mutable ones. I know that you are more likely to mess up and have
side effects with mutable data structures, but so far all I have heard is
theory.

~~~
couchand
The big win is they enable lazy evaluation: you can defer the evaluation of an
expression until it's needed, or discard the result and compute it again
later, or cache the result of an expression and not need to re-evaluate, a
flexibility which can be useful in many situations.

You also get undo/redo stacks basically for free, since you simply maintain
references to the previous n immutable states.

As Om demonstrates, they also make possible significant optimizations of code
that takes various view of the same underlying data, like rendering routines.

------
boubiyeah
What's the use of immutable data collections if you have to constantly revert
to mutable arrays to render anything? Any gain from the persistent collection
is lost in wasteful Array creating (Poor gc)

------
nawitus
Hmm, it seems to be written in TypeScript, but the source is only provided in
JavaScript.

~~~
leebyron
I actually started by writing it in TS and later moved to just a TS
declaration file and a raw JS source. This means it can be used smoothly in
both environments (similar to using a definitelytyped resource).

~~~
epignosisx
What made you go back to plain javascript?

