
Immer is a library of persistent and immutable data structures written in C++ - fortran77
https://github.com/arximboldi/immer
======
acemarke
Ironically, there's a name clash with a fairly popular immutable update
library for JS:

[https://github.com/immerjs/immer](https://github.com/immerjs/immer)

Looks like the C++ one started first (2016-05 vs 2017-12).

~~~
aidos
I assumed it was some sort of port, but they’re totally different things!

OT but it’s worth reading the code for immerjs. It’s super small, super clever
and shows the power of proxies in js.

~~~
acemarke
Yep. Michel Weststrate is a genius, and also an all-around nice guy. I hope to
have a chance to meet him in person.

(For reference, I'm a Redux maintainer. We now recommend Immer as the best way
to write immutable update logic in Redux apps, and use it in our Redux Starter
kit package.)

~~~
k3liutZu
Immer looks awesome but we're relying on Immutablejs shallow object comparison
to stop rendering React components when not needed. When I last checked I
could not figure out how to achieve the same thing with Immer.

Do you know some reference that addresses this?

And if we're here an additional question: since our store data is currently
composed of deep immutable JS data structures, do you know of a way to slowly
migrate to Immer?

I've tried to move parts of the store to Immer, but since the root store
obejcts are still Immutable js objects, this didn't go well.

~~~
thebosz
ImmerJS is a direct replacement for ImmutableJS.

We recently switched from using ImmutableJS in our Redux store to using
ImmerJS.

We took the approach one reducer at a time. We have multiple reducers and
we're using combineReducers (the ImmutableJS one until it was completely
converted).

We had no issues whatsoever in the change. ImmutableJS doesn't care about
plain JS objects (which is what ImmerJS reducers return) so everything worked
as expected.

React's shallow comparison worked as expected since ImmerJS produces new
objects on mutation (just like ImmutableJS).

Essentially: there is no case where ImmutableJS is needed. _All_ functionality
and benefits are available in ImmerJS which is a much easier to use library.

To do the migration, we literally just used the docs on the Github repo. This
was back with version 1.0 or something and it wasn't documented very well but
we were able to figure it out. The first code example is how to use it with
Redux. Also the section on Currying is useful.

Edit to add: This is all within the context of web apps, specifically React
apps with Redux. I'm sure there's probably __some __places where ImmutableJS
is desirable, but I don 't know of any.

~~~
__s
"there is no case" is a strong statement. ImmutableJS is generally the wrong
tool for the job in a reducer. It's optimized for if you have a single flat
object with 1000s of keys. Immer can't implement the same level of structural
sharing

~~~
aidos
Can you explain this scenario further? I’ve not used immutablejs but I’m
familiar with both functional data structure concepts and immerjs.

Immerjs just improves the ergonomics updating a native nested structure in a
way that the original contents are maintained as much as possible. Because js
has dreadful support for equality checks, this definitely comes in useful.

~~~
acemarke
Immutable.js implements a specific set of data structures that internally
share references. When you add a new field or copy an object, Immutable.js
doesn't have to completely recreate things. For small objects this doesn't
matter, but for _very_ large objects and arrays, it does improve performance
to some extent.

With Immer and "hand-written" immutable updates, doing a `{...obj}` or
`someArray.slice()` will do a "shallow" copy of the object. This is equivalent
to what Immutable.js does in that it keeps all the fields pointing to the same
references. However, the JS engine does have to do an O(n) processing of all
the individual top-level keys, whereas Immutable.js's internal data structure
is O(logN) or something like that. So, for _very_ large objects, it is faster
for Immutable.js to make a copy than it is for plain JS data.

My take, however, is that

\- Most apps will not be dealing with gigantic objects, so there's no perf
benefit from using Immutable.js

\- Immutable.js is a much larger dependency than Immer

\- The fact that Immer works with POJOs _and_ gives you the ability to write
trivial "mutative" syntax for updates is a huge improvement over
Immutable.js's Java-inspired API

So, to me, the only hypothetical use case where Immutable.js would actually be
worth it is if your app is consistently dealing with huge objects, _and_ there
is truly serious overhead from copying them that needs to be optimized.

------
spraak
For some perspective on why the name was probably chosen: 'immer' means
'forever' or 'always' in German

------
ur-whale
Could someone provide an actual example use-case for immutable data structures
in C++?

The linked document only mentions high-level examples, all of which seem to be
trivially implementable via mutable data structures and a bit of being
careful.

Does this buy anything beyond peace of mind that if you pass an immutable DS
to another thread, they won't be able to change it?

~~~
stabbles
The author has created a text editor which uses immutable data structures s.t.
he can do fast undo / redo [1]

[1] [https://github.com/arximboldi/ewig](https://github.com/arximboldi/ewig)

~~~
bjoli
I saw a demonstration where he copy pasted a file into itself until it was
larger than whatever memory he had in the computer. He could still efficiently
edit it (the data pointers were duplicated, not the data).

Pretty impressive.

~~~
johnisgood
Do you have the URL to the video?

------
rgovostes
The Clang Static Analyzer uses immutable data structures. Here, for instance,
is its immutable list implementation: [https://github.com/llvm/llvm-
project/blob/master/llvm/includ...](https://github.com/llvm/llvm-
project/blob/master/llvm/include/llvm/ADT/ImmutableList.h)

The data structures are used during program state exploration because they are
more memory efficient than storing many copies of the program state with small
mutations.

------
siempreb
There is something about this immutability thing I really don't like. In the
authors example it looks like v1[0] is set to 42 (const auto v2 = v1.set(0,
42)), at least that's how you read it because it contains the word 'set', but
you have to 'know' that v1 is immutable and is actually not setting the value,
but returning it. So IMAO the naming should be better, I like to read code
that is not confusing.

If this construct, that I actually never needed in my entire career, is handy
for undo/redo, why not just have a dead simple undo stack? In what situation
is an immutable structure your best choice?

~~~
agumonkey
what would be a good word for this ? recreate ? recompute ? with_new ?

~~~
ScottBurson
In general, I think verbs should be avoided, when possible, as names of
functional operations. For instance, in Java, 'BigInteger.add' should have
been 'plus'. Compare:

    
    
      x.add(y);
      x.plus(y);
    

People have been known to write the first one expecting 'x' to be updated.
With the second, I think it's clearer that it's a value that needs to be
assigned to a variable.

For the operation in question here, I suggest 'with'. This is what I have used
in my own functional collections libraries; I think it originated in SETL.

~~~
skohan
I am a fan of nouns(or gerunds) for pure functions, and verbs for mutating
functions. I.e:

    
    
        x.add(y); // x now equals x + y 
        x.adding(y); // returns x + y without mutating x

------
saagarjha
Related: it’d be great if C++ had const constructors, so that we could have
true const objects.

~~~
leni536
What would be the utility of such a constructor? You can just initialize const
objects with regular constructors. How are these objects not "true" const?

~~~
saagarjha
The specific use case I had in mind was a implicit “conversion” constructor
that took an immutable object and gave back something that you couldn’t strip
the const off of (it’d also take a mutable object and give you a normal thing
back). What I have specifically is a class that provides a base set of
operations and a subclass that lets you do some modifications, and what I am
trying to do is wrap it in C++ with an object that is const depending on which
class I am converting (converting object to const wrapper_class and
mutable_object, a subclass of object, to just wrapper_class).

~~~
munchbunny
> What I have specifically is a class that provides a base set of operations
> and a subclass that lets you do some modifications

Your object isn't actually immutable, it just doesn't let you directly mutate
it. That's a really important distinction.

That's a common pattern. In C++, rather than using a subclass for the mutator,
use a different (friend) class. The semantics for implicit conversion between
two different classes will allow you to accomplish what you are asking for
with enforcing no changes from one interface but not the other.

~~~
saagarjha
> In C++, rather than using a subclass for the mutator, use a different
> (friend) class.

Unfortunately I don't control this class :(

