←back to thread

498 points azhenley | 6 comments | | HN request time: 0.264s | source | bottom
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 #
1. dwwoelfel ◴[] No.45773479[source]
Carmack is talking about variable reassignment here, which Clojure will happily let you mutate.

For example:

  (let [result {:a 1}
        result (assoc result :b 2)]
    ...)

He mentions that C and C++ allow const variables, but Clojure doesn't support that.

clj-kondo has a :shadowed-var rule, but it will only find cases where you shadow a top-level var (not the case in my example).

replies(2): >>45773913 #>>45774145 #
2. didibus ◴[] No.45773913[source]
It's more nuanced, because the shadowing is block-local, so when the lexical scope exits the prior bindings are restored.

I think in practice this is the ideal middle ground of convenience (putting version numbers at the end of variables being annoying), but retaining mostly sane semantics and reuse of prior intermediate results.

replies(1): >>45774454 #
3. manoDev ◴[] No.45774145[source]
That's not mutation though.

The `assoc` on the second binding is returning a new object; you're just shadowing the previous binding name.

This is different than mutation, because if you were to introduce an intermediate binding here, or break this into two `let`s, you could be holding references to both objects {:a 1} and {:a 1 :b 2} at any time in a consistent way - including in a future/promise dereferenced later.

replies(2): >>45774328 #>>45778688 #
4. ◴[] No.45774328[source]
5. ◴[] No.45774454[source]
6. potetm ◴[] No.45778688[source]
regardless of the mechanism, you still run into the exact same problem John had.