Here you go, I had to use even more macro magic but it works (for objects at
least). I tried to write some descriptive comments to describe what happens but
the summary is that we basically unrolls the loop in `createAllVar` at
compiletime so we don't have the issues with scopes:
import macros
type
Person = object
name: string
age: int
proc nameToVarAssign(it: NimNode, fieldName: string): NimNode =
let varIdent = ident(fieldName) # create the identifier for the field and
the variable
let dotExpr = newDotExpr(it, varIdent) # create it.field expression
result = quote do: # create the assignment expression
var `varIdent` = `dotExpr` # var field = it.field
macro createAllVar(it: typed): untyped =
result = newStmtList()
let fieldList = it.getType[2] # this is the list of field names
for fieldName in fieldList: # iterate over all fields and generate the
variable assignments
result.add(nameToVarAssign(it, fieldName.strVal))
template filter(s, pred: untyped): untyped =
var result = newSeq[typeof(s[0])]()
for it {.inject.} in items(s):
createAllVar it
if pred: result.add(it)
result
let people = @[ Person(name: "wk", age: 20), Person(name: "jw", age: 22)]
let rs = filter(people, age > 20 and name == "jw")
echo rs
Run