←back to thread

498 points azhenley | 4 comments | | HN request time: 0.001s | source
Show context
EastLondonCoder ◴[] No.45770007[source]
After a 2 year Clojure stint I find it very hard to explain the clarity that comes with immutability for programmers used to trigger effects with a mutation.

I think it may be one of those things you have to see in order to understand.

replies(17): >>45770035 #>>45770426 #>>45770485 #>>45770884 #>>45770924 #>>45771438 #>>45771558 #>>45771722 #>>45772048 #>>45772446 #>>45773479 #>>45775905 #>>45777189 #>>45779458 #>>45780612 #>>45780778 #>>45781186 #
rendaw ◴[] No.45770924[source]
I think the explanation is: When you mutate variables it implicitly creates an ordering dependency - later uses of the variable rely on previous mutations. However, this is an implicit dependency that isn't modeled by the language so reordering won't cause any errors.

With a very basic concrete example:

x = 7

x = x + 3

x = x / 2

Vs

x = 7

x1 = x + 3

x2 = x1 / 2

Reordering the first will have no error, but you'll get the wrong result. The second will produce an error if you try to reorder the statements.

Another way to look at it is that in the first example, the 3rd calculation doesn't have "x" as a dependency but rather "x in the state where addition has already been completed" (i.e. it's 3 different x's that all share the same name). Doing single assignment is just making this explicit.

replies(10): >>45770972 #>>45771110 #>>45771163 #>>45771234 #>>45771937 #>>45772126 #>>45773250 #>>45776504 #>>45777296 #>>45778328 #
skeezyjefferson ◴[] No.45771110[source]
whats the difference between immutable and constant, which has been in use far longer? why are you calling it mutable?
replies(4): >>45771178 #>>45771248 #>>45773965 #>>45774112 #
inanutshellus ◴[] No.45771248[source]
"Constant" implies a larger context.

As in - it's not very "constant" if you keep re-making it in your loop, right?

Whereas "immutable" throws away that extra context and means "whatever variable you have, for however long you have it, it's unchangeable."

replies(1): >>45773019 #
skeezyjefferson ◴[] No.45773019{3}[source]
> As in - it's not very "constant" if you keep re-making it in your loop, right?

you cant change a constant though

replies(1): >>45773195 #
veilrap ◴[] No.45773195{4}[source]
He’s implying that the variable it’s being defined within the loop. So, constant, but repeatedly redefined.
replies(1): >>45773473 #
ghurtado ◴[] No.45773473{5}[source]
That's the opposite of what any reasonable engineer means by "constant".
replies(2): >>45774034 #>>45774230 #
1. fnordsensei ◴[] No.45774034{6}[source]
That’s the point, you’re just haggling about scopes now. All the way from being new per program invocation to new per loop.

Immutability doesn’t have this connotation.

replies(1): >>45774245 #
2. davrosthedalek ◴[] No.45774245[source]
How? I think the same argument applies: If it's changing from loop to loop, seems mutable to me.
replies(2): >>45774345 #>>45776074 #
3. fnordsensei ◴[] No.45774345[source]
I think you’re after something other than immutability then.

You’re allowed to rebind a var defined within a loop, it doesn’t mean that you can’t hang on to the old value if you need to.

With mutability, you actively can’t hang on to the old value, it’ll change under your feet.

Maybe it makes more sense if you think about it like tail recursion: you call a function and do some calculations, and then you call the same function again, but with new args.

This is allowed, and not the same as hammering a variable in place.

4. Zambyte ◴[] No.45776074[source]
I can give a specific example.

    for (0..5) |i| {
        i = i + 1;
        std.debug.print("foo {}\n", .{i});
    }
In this loop in Zig, the reassignment to i fails, because i is a constant. However, i is a new constant bound to a different value each iteration.

To potentially make it clearer that this is not mutation of a constant between iterations, technically &i could change between iterations, and the program would still be correct. This is not true with a c-style for loop using explicit mutation.