
Why care about functional programming? Part 1: Immutability - nathankot
http://miles.no/blogg/why-care-about-functional-programming-part-1-immutability
======
taeric
I can't make it past the first sentance in the opening without just wanting to
scream in annoyance. Nothing about immutable objects means that you are going
to write thread safe code. Pretty much period.

Worse, nothing about functional programming is necessarily about immutability.
It is a convenience on small and easy problems, but is far from required.
Consider how your computer adds two numbers. Lots of things change state under
highly timed situations to give you that answer. It is not some magic table
lookup that works with immutable facts.

I may just be bitter by a system right now that is using immutable objects
everywhere. I realize this is a straw man, but with heavy reliance on deep (3+
levels) of immutable relationships, it is not uncommon to find crap that is
the equivalent of this:

    
    
        String foo = "hello";
        Character bar = foo.charAt(0);
    
        ...
        //We need to make sure bar is capitalized everywhere
        baz = bar.toUpperCase();
        //Now to find everywhere this matters and let the caller know.
    

I realize lenses and zippers and such _can_ help, but so can just being a bit
more disciplined about using modifiable items in the first bloody place.

~~~
tel
Obviously this is just a short fragment and explicitly it's a straw man, but I
can't help but get this incredibly strong feeling that this code is
immutability bolted on instead of embraced. Lenses, yes, could be used to
solve something like this, but it feels like you're facing a problem which is
better avoided than fixed.

I'm not really trying to rain on your tirade---surely there are ways to misuse
immutability---but I can't look at this example and not feel that immutability
is telling you something about a better architecture.

~~~
taeric
Oh, I certainly agree. And really... this is my point. Misused immutability is
just as garbage heavy as misused mutability. It does not, ipso facto, prevent
bugs or make threaded code easy to do.

------
deepsun
No one prevents you to use immutable structures in OOP.

Getting some help from language is nice, but after 10+ years of programming
all those patterns (e.g. immutable) become so natural, that you don't really
think much about them. Because you know what data structure you want, and see
what language offers you. So the whole "which language" deal doesn't make so
much difference (although it's easier/harder in some languages). Tooling/libs
and community matters way more.

~~~
the_af
> _No one prevents you to use immutable structures in OOP._

No one prevents you, but what about the code other people write?

~~~
deepsun
Good point. Fortunately, I had pretty good engineers in my recent teams, but,
remembering my older projects, I totally agree with you that it's good when
language makes it hard to write bad code for less competent engineers.

------
phkahler
That's an awful lot of text to advocate for immutable data to prevent shooting
yourself in the foot when things go concurrent.

I've got this renderer that takes a huge data structure and uses simple OpenMP
constructs to draw images. There is an assumption that the underlying data
will not change during a render. Do I need a functional language to enforce
this? No. Would it be nice if C++ had a feature to enforce it? Yes. Will I
eventually want to make something that can carefully modify the data while
rendering? Maybe, but I'm not sure that even makes sense.

I think a bigger threat is event driven code which IMHO is notorious for
making things happen in unexpected order.

~~~
sirseal
I'm not that great at C++, but can't you use the const keyword to declare that
something's value isn't changing?

~~~
tjradcliffe
You can. If you want to write immutable C++ simply declare every single
variable const. Done.

The only difference between C++ and "immutable by design" languages is that in
C++ you'd have to write your own little processor to ensure that your rule is
followed (this is no big deal, and I've written much more complex processors
to enforce C++ coding standards as part of the build.)

------
skybrian
Immutability is basically like explicit version control. If the program is
interactive, sooner or later you need to write a state machine that updates
HEAD. A good example is the foldp function in Elm. [1]

You can probably do this in any language, but efficiency is another issue.

[1] [http://package.elm-lang.org/packages/elm-
lang/core/1.1.1/Sig...](http://package.elm-lang.org/packages/elm-
lang/core/1.1.1/Signal#foldp)

~~~
TheOtherHobbes
Immutability is nothing like explicit version control. So far as I know no
language has anything close to explicit version control for state.

This is unfortunate, because it could potentially be a very useful if every
single atom of data came with a built-in list of previous states, with
timestamps, and with an identifier for the code/process that last changed the
state.

Obviously, this is usually what debuggers try to do. But there's no reason why
something like this couldn't be built into a language.

(Yes, it would be slow. No, it wouldn't be _that_ slow if done right. It
wouldn't even have to be slower than many other standard practices. But yes,
it could potentially use a lot of memory unless given a cutoff. Even so...)

CS generally still seems stuck in the "memory is a line pigeonholes" model,
and immutability seems to be a crude memory management hack, not a complete
state control solution.

I sometimes wonder if a lot of the issues with state are caused by the fact
that languages have extremely limited tools for dealing explicitly with
representations of historical causality and past/present/future, and not
because state itself is inherently evil.

~~~
cfallin
> Immutability is nothing like explicit version control. So far as I know no
> language has anything close to explicit version control for state.

Well, it depends on which version control system we're imagining. In my mind,
the immutable data-structure approach is like git, and I _think_ what you're
imagining is more like CVS.

Consider: immutability by itself doesn't enforce versioning; it just makes the
state-of-the-world equivalent to state-of-the-root-pointers-of-your-heap,
because the pointed-to things cannot change. (I.e., referential transparency.)
So it pushes the versioning up to whatever agents manage the root pointers.
This is sort of like git: you build an immutable DAG, and you have mutable
HEAD pointers that move around in it. (The difference is that git has one HEAD
for the tree while this world has one HEAD per global or stack-local root.)
When you have a reference, you have a snapshot of the world in time that will
never change.

Your "each slot has a list of previous states" is more like CVS in that it
versions each "file" separately. This is also useful, but for a different
reason: sometimes you really do want that history as a first-class concept.
You can derive the per-file history in a git-like system too but it involves
some computation. (And coming back from the analogy, in such a memory-
management scheme, you would need to formalize the changes to root pointers
into some sort of transaction system.)

All of that said, I think what you describe would be really useful for
debugging, albeit probably pretty expensive (each store instruction touches an
undo log?). Time-reversible debuggers may have done something like this?

~~~
skybrian
Yes, Elm has a "time travelling debugger" though I haven't really used it.

[http://debug.elm-lang.org/](http://debug.elm-lang.org/)

------
brudgers
_If you do not care about mutability, you will only get immutable data. You
can then send the data between different threads, and it will not get
corrupted. The reason is that whenever you attempt to change them, a new
instance of the structure being changed will be allocated._

There is a lot to recommend a functional programming style in general and
forgoing mutation of data in particular, but these are programming practices.
Clojure allows mutation. Common Lisp allows it in ways that are as mind
blowingly difficult to grok as macros. The shared structure that allows
efficient immutability semantics allows a tsunami of value changes if someone
is careless or malicious.

~~~
wtetzner
Clojure allows mutation, but the data structures that use structural sharing
aren't mutable.

------
niche
Look, I care about functional programming, I just haz no reason to use it atm

Cheers!

