←back to thread

498 points azhenley | 3 comments | | HN request time: 0s | 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 #
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 #
1. 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 #
2. ◴[] No.45774328[source]
3. potetm ◴[] No.45778688[source]
regardless of the mechanism, you still run into the exact same problem John had.