Semantics of let assignment in Nim
I was recommended the Nim programming language and started reading through the Tutorial 1, the Manual and even the memory model (in particular the section about strings and seqs).
I soon encountered some strange behavior regarding let assignment which doesn't seem to make any sense at all, to the point of appearing a complete mess. I can demonstrate all the nonsense with this simple script (link to playground):
echo "first example:"
proc p =
var msg = "Hello"
let copy = msg
msg.add(" World!")
echo msg
echo copy # does NOT change
p()
echo "\nsecond example:"
proc q =
var msg = "Hello"
let copy = msg
msg.add("!")
echo msg
echo copy # DOES change
q()
echo "\nthird example:"
var msg = "Hello"
let copy = msg
msg.add("!")
echo msg
echo copy # does NOT change
In the first and third examples, copy retains the original value "Hello". The second example (proc q) shares a similarity with the other two cases:
- it is similar to the first because it employs the local scope of a
proc, - it is similar to the third because it appends the same string (
"!").
For some arcane reason however, in the first and third examples copy is indeed a copy (bind by value?), whereas in the second example the modification to the variable msg propagates to the immutable copy (bind by reference?).
What is going on? How can we make sense of this? Does let bind by value or by reference? If it make sense somehow, why is it not explained clearly and in depth in the official guides?
I found strange thing:
At top-level string variable just copied, but in procedures small changes looks like changing pointers, but big changes looks like copy ...
I'm trying to change
lettovarand here is not changes.I think that reason is compiler bug.