That could work. I would be concerned about something though: will binary zero
always mean that it is safe to change branches? It is possible that a varient
may be perfectly valid as zero, even when initialized. An example could explain
better:
type
Variant = enum
Point, NamedPoint
Point2d = object
case kind: Variant
of Point:
x, y: float
of NamedPoint:
name: string
nx, ny: float
Just having the point at (0, 0) doesn't mean that the programmer intends for a
Point to be reinterpreted as a NamedPoint. In fact, if you have, for example,
some game entities, then those at the origin would have different assignment
properties. I'm afraid that this could be surprising, if not dangerous. So, I
like the idea, but I fear that it could create unexpected corner cases.
I have an idea, and although it's a bit silly/simple, it could be advisable.
Maybe we could urge developers to have a "nil case" that has no fields,
especially in more critical code. That would place the burden on the
programmer, but it's also very deliberate. The object could only be initialized
into this state, and then the branch would be set in stone until `reset`:
type
Variant = enum
None, Point, NamedPoint
Point2d = object
case kind: Variant
of None: discard
of Point:
x, y: float
of NamedPoint:
name: string
nx, ny: float
var p = Point2d(kind: None)
p.kind = Point
p.x = 3.0
p.y = 2.0
echo p.x, ' ', p.y
# Throws FieldError, as intended.
p.kind = NamedPoint
This seems like a workaround in some ways, though, and current code does not do
this. It would be better if the language could enforce the variants without
such a construction. I do understand the argument about flexibility. Nim
developers are almost certainly going to assign to different fields, including
the discriminant, after obtaining a `new`, zeroed object.