I have an object defined like this:
Obj = ref object
case kind: ObjKind:
of typeA, typeB: contents: seq[Obj]
else: discard
Then I create an object like that:
example = Obj(kind: typeA, contents: @[some contents])
at some point, let's say I decide to change the object's kind (but without changing its contents field). I do it like this:
.kind = typeB
Now, it seemingly works fine. The problem is the contents field's contents are gone (the only way to get them back is by keeping a copy of the previous contents, change the kind and re-set the contents).
Any idea what is going on or what the best way to do it would be?
Changing the kind effectively erase the object. This is due to the semantics of variant which are supposed to represent different runtime types and changing the kind would reinterpret the potentially garbage-filled fields.
Note that things might have change in devel after this RFC was implemented: https://github.com/nim-lang/RFCs/issues/209
If that RFC didn't change anything you can:
type ObjKind = enum
typeA, typeB
type ObjField{.union.} = object
fieldA: int
fieldB: float
type Obj = object
kind: ObjKind
f: ObjField
what the best way to do it would be
Don't make kind a case variant:
type
ObjKind = enum typeA, typeB
Obj = ref object
kind: ObjKind
contents: seq[Obj]
if that doesn't work for your actual use case, then you need to provide more info. To me, just changing the kind of an object variant without changing the whole object doesn't make semantic sense.
(BTW, if your object is really defined like that, you probably want to add an {.acyclic.} pragma.)
Use your own {.union.} object like so
The manual says that GC isn't done on the content of unions (which matters for the OP's code, not yours) ... is that no longer the case?