Hello, how would I merge two objects?
I see fieldPairs in 'system/iterators' but there is a note about a symBind bug.
The idea is to overwrite the values in object A fields, with object B's fields. (the fields are option types so we only overwrite if the field isSome, alternatively nil or default) A and B are both of the same type of course.
This is non-trivial, since Nim is not a dynamic language, so there is no easy way to set an object field by field name. It can be done with a macro, though.
Using the macro from this thread: https://forum.nim-lang.org/t/4573#28714
import std/[macros, options]
macro `[]=`*(obj: var object, fieldName: string, value: untyped): untyped =
## Set object field value by name: ``obj["field"] = value`` translates to ``obj.field = value``.
newAssignment(newDotExpr(obj, newIdentNode(fieldName.strVal)), value)
type
Foo = object
bar: Option[int]
baz: Option[float]
spamm: Option[string]
var foo_a = Foo(bar: some(42), baz: some(3.141), spamm: some("Ni!"))
echo $foo_a
let foo_b = Foo(bar: some(23), spamm: some("'Sup?"))
echo $foo_b
for name, value in foo_b.fieldPairs:
if value.isSome:
foo_a[name] = value
echo $foo_a
fieldPairs is the way to go:
import std/[options, sugar]
type
Foo = object
bar: Option[string]
baz: Option[string]
var a = Foo(bar: "a's bar".some, baz: "a's baz".some)
let b = Foo(bar: string.none, baz: "b's baz".some)
dump a
dump b
for name, aVal, bVal in fieldPairs(a, b):
when bVal is Option:
if bVal.isSome:
aVal = bVal
dump a
doAssert a == Foo(bar: "a's bar".some, baz: "b's baz".some)