Mapping objects in place (aka merging 2 objects)
Basic Usage
Instead of creating a new object you may want to update some of the fields on an instance of A
with the values contained in B
.
This can be done via the inplaceMap
pragma.
All it requires is 2 things:
- The proc that you define must not have a return type, as this is for mapping 2 objects in place, not producing a new one.
- There must be at least 2 parameters in order to have something to map inplace.
The first parameter is implicitly assumed to be the one to inplace-map the other parameters to.
import mapster
type A = object
str: string
type B = object
str: string
proc mergeWithB(y: var A, x: B) {.inplaceMap.} = discard
var a = A()
var b = B(str: "Something")
a.mergeWithB(b)
doAssert a == A(str: "Something")
Multiple parameters
Similar to map you can also inplace-map multiple parameters at once. Note that in case multiple parameters map to the same field, the last parameter's field will be transferred.
type C = object
str: string
proc mergeWithAB(y: var C, x1: A, x2: B) {.inplaceMap.} = discard
proc mergeWithBA(y: var C, x1: B, x2: A) {.inplaceMap.} = discard
let a2 = A(str: "AValue")
let b2 = B(str: "BValue")
var resultAB: C = C()
resultAB.mergeWithAB(a2, b2)
var resultBA: C = C()
resultBA.mergeWithBA(b2, a2)
let expectedAB = C(str: "BValue")
let expectedBA = C(str: "AValue")
doAssert resultAB == expectedAB
doAssert resultBA == expectedBA
Excluding/ignoring parameters
Also similar to map
with mapExcept
there is inplaceMapExcept
for inplaceMap
.
This allows you to ignore parameters from automatically getting inplace-mapped into your object.
import mapster
type A3 = object
str: string
type B3 = object
num: int
type C3 = object
str: string
num: int
let a3 = A3(str: "str")
let b3 = B3(num: 5)
proc mergeWith(c: var C3, a: A3, b: B3) {.inplaceMapExcept: "b".} = discard
var myC3: C3 = C3(str: "", num: 2)
myC3.mergeWith(a3, b3)
let expected3 = C3(str: "str", num: 2)
doAssert myC3 == expected3