This is simply caused by template hygiene. In case `values` was defined in the 
scope you called `runWithBody` it would throw an error if `values` got 
redefined there. The solution is to mark `values` as injected, that was Nim 
makes it visible to the `body` port of your code:
    
    
    var callback: proc(args: varargs[int]): string # this line shouldn't change
    
    template runWithBody(minLength: int, body: untyped) =
      proc localFunc(values {.inject.}: openArray[int]): string =
        if values.len >= minLength:
          body
        else:
          raise newException(ServerException, "Called function contains less 
than " & $minLength & " arguments")
      callback = proc(args: varargs[int]): string =
        localFunc(args)
    
    runWithBody(2):
      result = $(values[0] + values[1]) # here is the problem:  Error: 
undeclared identifier: 'values'
    
    print callback(1, 2, 3) # this line also shouldn't change, if possible.
    
    
    Run

The alternative is to mark your entire template as `{.dirty.}`, but that would 
make `localFunc` also visible and would cause an error if you ever called your 
template twice (because now you would redefine `localFunc`).

Of course you can also drop the `proc localFunc` part entirely and just do this 
(modified slightly so I could run it in the playground without errors):
    
    
    var callback: proc(args: varargs[int]): string # this line shouldn't change
    
    template runWithBody(minLength: int, body: untyped) =
      callback = proc(values {.inject.}: varargs[int]): string =
        if values.len >= minLength:
          body
        else:
          raise newException(Exception, "Called function contains less than " & 
$minLength & " arguments")
    
    runWithBody(2):
      result = $(values[0] + values[1]) # here is the problem:  Error: 
undeclared identifier: 'values'
    
    echo callback(1, 2, 3) # this line also shouldn't change, if possible.
    
    
    Run

Reply via email to