type
FooEnum = enum
Stringer, Numberer
Foo = object
case kind: FooEnum
of Stringer:
x: string
of Numberer:
y: int
let
a = Foo(kind: Stringer, x: "hi")
b = Foo(kind: Stringer, x: "hello")
echo (a == b)
This reports Error: parallel 'fields' iterator does not work for 'case' objects
It is in principle possible to write a macro for algebraic data types that generates both the declaration and an implementation of == for that type. You'd have something like:
macro variant(e: expr, s: stmt): stmt {.immediate.} =
...
variant Foo:
Alpha(i: int)
Beta(f: float)
Gamma(s: string)
Which would generate code like this (eliding visibility markers and handwaving name generation for simplicity);
type FooKind = enum FooAlpha, FooBeta, FooGamma
type Foo = ref object
case kind: FooKind
of FooAlpha:
i: int
of FooBeta:
f: float
of FooGamma:
s: string
proc Alpha(arg: int): Foo =
Foo(kind: FooAlpha, i: arg)
proc Beta(arg: float): Foo =
Foo(kind: FooBeta, f: arg)
proc Gamma(arg: string): Foo =
Foo(kind: FooGamma, s: arg)
proc `==`(a, b: Foo): bool =
if a.kind != b.kind:
false
else:
case a.kind
of FooAlpha:
a.i == b.i
of FooBeta:
a.f == b.f
of FooGamma:
a.s == b.s
https://gist.github.com/flaviut/53b7f1928c944c010605
Not quite the same thing, it uses inheritance, but it shows how this sort of thing can be done with macros. I might convert it to use case statements later.