Minimal example:
type
ObjKind = enum
A
B
C
Obj = ref object
case kind:ObjKind:
of A: s: string
of B: i: int
of C: a: seq[Obj]
let VEMPTYARR = Obj(kind: C, a: @[])
func `$`(o: Obj): string =
case o.kind:
of A: "A(" & o.s & ")"
of B: "B(" & $o.i & ")"
of C: "C(" & $o.a & ")"
when isMainModule:
var x = VEMPTYARR
x.a.add(Obj(kind: B, i: 1))
x.a.add(Obj(kind: B, i: 2))
echo $(x)
var z = VEMPTYARR
z.a.add(Obj(kind: A, s: "hello"))
z.a.add(Obj(kind: A, s: "world"))
echo $(z)
The result is:
C(@[B(1), B(2)])
C(@[B(1), B(2), A(hello), A(world)])
Now, I look at the generated code and clearly see 2 eqcopy__ statements for each of the assignments (x and z).
But apparently, .add changes a internally, meaning the .a field of VEMPTYARR...
When I re-compile with nim c -d:danger --mm:orc adding --deepCopy:on and make the assignment with deepCopy(), it does work, but then it becomes ultra slow.
So, what is going on? The = leads to a copy, which copies... what exactly?
You can force a deepcopy of one specific ref object with deepCopy. Looking at a RosettaCode example https://rosettacode.org/wiki/Deepcopy#Nim I found that you could do (on a smaller minimal example):
type
ObjKind = enum
B
C
Obj = ref object
case kind:ObjKind:
of B: i: int
of C: a: seq[Obj]
let vemptyarr = Obj(kind: C, a: @[])
func `$`(o: Obj): string =
case o.kind:
of B: "B(" & $o.i & ")"
of C: "C(" & $o.a & ")"
var x:Obj
x.deepCopy vemptyarr
x.a.add(Obj(kind: B, i: 1))
x.a.add(Obj(kind: B, i: 2))
echo $(x)
var z = vemptyarr
z.a.add(Obj(kind: B, i: 3))
z.a.add(Obj(kind: B, i: 4))
echo $(z)
It does slow down quite a lot. I am curious of the internal representation of the object. You have both a recursive type with a case of field. You ask Nim to copy sequences of sequences of sequences ...
I don't know how the memory layout of recursive sequence types looks. How do you copy it efficiently ? Since sequences are nested, we don't know without exploring the full tree, the exact size of the object.
proc copyOneLevel(n: Obj): Obj =
result = Obj()
result[] = n[]
Now give me my cigar.
No, it's not unique nor hard. Personally, I'm all for pointers.
The problem is I find some inconsistencies (mostly stemming from a combination of the GC + the seq values), or things working too automagically - for me - that it's not always that clear what is going on behind the scenes...
"Jesus Christ these things are neither hard nor unique to Nim."
Come on Araq, this is no way of answering any kind of question on the forum, especially from someone in your position.
It's pretty tame. 🤷
I like Nim and would very much like it if it became more popular. I agree with @zevv that you, for better or worse, the face of Nim, answering a question that way on a forum, is unseemly. It would have been better to not respond at all.