Consider the following code to create linked list-like structure:
type
A = ref AObj
AObj = object
id: int
parent: A
child: A
proc `$`(a: A): string = $a.id
proc takeAsVar(curr: var A, next: A) =
if curr == nil:
curr = next # var A is wanted here and nowhere else
else:
let const_curr = curr
echo "takeAsVar: curr before: ", curr
curr.parent.child = next # Try changing curr to const_curr for same
result
echo "takeAsVar: curr after: ", curr
# curr changes even though there is no "curr = ..." line.
proc takeAsConst(curr: A, next: A) =
if curr == nil:
#curr = next # can't do this
discard
else:
echo "takeAsConst: curr before: ", curr
curr.parent.child = next
echo "takeAsConst: curr after: ", curr
let a1 = A(id: 1, parent: nil, child: nil)
let a2 = A(id: 2, parent: nil, child: nil)
let a3 = A(id: 3, parent: nil, child: nil)
a1.child = a2
a2.parent = a1
takeAsVar(a1.child, a3)
let a4 = A(id: 4, parent: nil, child: nil)
let a5 = A(id: 5, parent: nil, child: nil)
let a6 = A(id: 6, parent: nil, child: nil)
a4.child = a5
a5.parent = a4
takeAsConst(a4.child, a6) # Works as expected
which outputs
takeAsVar: curr before: 2
takeAsVar: curr after: 3
takeAsConst: curr before: 5
takeAsConst: curr after: 5
Notice how the value of the variable curr changes in the first proc without an
explicit curr = ....
We have a very simple object with a parent pointer and a child pointer. My
initial goal was to create a linked list-like structure and inserting into a
nil list could be handled by taking the original list by var since it allows
for curr = next. Most of the logic for non-nil list has been removed to get a
minimum working example, but the problem is this: When I want to change the
child field of the parent of curr, then the variable curr itself is changed
when taken by var.
In my mind taking a parameter by var would only change whether you can write
curr = ... and change the original or not. Here it seems that it somehow infers
that curr.parent.child is the same as curr and changes curr as well.
Have I misunderstood how var parameters work? Is this desired behaviour?
Using version 0.16.1 (git hash: 137b5f43022c3c5e22a7f28c8012f1d0ea6007c6)