I am trying to understand some behaviour I have noticed in Clojure.
It is possible to create a let binding with the same binding-name repeated multiple times:
(let [a 1 a 2 a b] a)
; (= a 2)
(let [a 1 a 2 a 3] a)
; (= a 3)
I understand that let bindings are evaluated, and this all mostly makes sense.
My understanding from the docs is that "Locals created with let are not variables. Once created their values never change!"
Does the above syntax actually change the value of the bindings?
This feels like it should raise an error.
As a sort of side note:
Interestingly you can output the above as JS with clojurescript:
var a__36584 = 1, b__36585 = 2, a__36586 = b__36585;
var a__30671 = 1, a__30672 = 2, a__30673 = 3;
Here we can see that the values are all actually distinct variables, which points to what is happening under the covers, but some clarification would be very helpful.
(let [a 1, a 2] a)
is functionally equivalent to (let [a 1] (let [a 2] a))
, which may be easier to understand. In the latter case, it is relatively easy to realize that you're not "modifying" the value of a
, but introducing a new, unrelated variable named a
with a different value. You can see the effect of this with something like (let [a 1] (let [a 2] (println a)) a)
- it prints 2, and then returns 1, because the outer a
is never changed, only temporarily hidden. (let [a 1, a 2] a)
is simply introducing a value named a
that immediately goes out of scope. Of course, the outer a
is available until the inner a
has a value, so you can do something like (let [a 1, a (inc a)] a)
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With