Proper enums would be elegant, not this.
Proper enums would be elegant, not this.
type Foo interface { A | B | C }
and the interface type is the union of those type-sets. Such interfaces can not currently be used outside of type constraints, but if that is relaxed, and type switches are updated to support and enforce exhaustive matching (and understand such sealed / nominative interfaces), you've got all the bits you need.You'd need to newtype variants to add payloads of similar underlying type e.g. `int | int`, but that's not a huge imposition, and the variants being types themselves is often convenient so it's a 50:50 tradeoff compared to classic sum type (where constructors disambiguate all variants but are not themselves types).
var foo interface{ A | B }
then foo either has to be boxed (so the default value is a nil interface) or unboxed and arbitrarily initialized as an A or a B.I don't see how unboxing would have to be "arbitrarily initialized as an A or a B" either. Even with a novel bespoke implementation you still need a discriminant between the two nested. You could keep a nil default by reserving the zero discriminant for that purpose.
I think it would be weird if an unboxed union of A and B was initialized to a value that wasn't the default value of either A or B, although I take your point that it's a technically possible implementation.
Yep, fixed, sorry about that.
> I think it would be weird if an unboxed union of A and B was initialized to a value that wasn't the default value of either A or B
On the one hand yes, on the other hand it would be consistent with the langage semantics (the default value of an interface type is a nil), and I don’t think defaulting to the default value of an arbitrary variant is better.
Although I can see the similarity with iota / newtype constants, the first item being the default, and similarly people could set the first type as relevantly named (possibly unexported) empty struct if they want / need the signal.