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

Reply via email to