First code:

Let's start with why any of this template's instantiation won't compile --- it 
has a type error. "44" is a string but you assign it to an int variable. In 
fact, Nim's type inference makes it redundant for you to specify these 
variables' types.

Secondly: templates provide something called hygiene. It means that what you 
see inside the template is a _local_ name. In fact, a new name is generated 
each time a template is instantiated. For example:
    
    
    template someCode(): untyped =
      var
        fname: string = "Mark"
        age: int = 44
    
    someCode()
    someCode()  # ok, this instantation's `fname` is a NEW `fname`
    

To avoid this and inject symbols directly into the scope of instantiation, 
{.inject.} pragma should be used:
    
    
    template someCode(): untyped =
      var
        fname {.inject.}: string = "Mark"
        age {.inject.}: int = 44
    
    someCode()
    someCode()  # error, redefinition of `fname`
    
    echo fname  # compiles, prints "Mark"
    

Second code:

Unluckily, Nim's no Lisp. A template or macro call is first parsed as a call 
and _then_ substituted with the code yielded. It's quite unfortunate for some 
cases but if your example code is more-or-less what you need, here is a 
solution:
    
    
    template someCode(name: untyped): untyped =
      type name {.inject.} = object
        fname: string
        age: int
    

By the way... Funny thing...
    
    
    type name = object
      fname: string   # Error: cannot use symbol of kind 'var' as a 'field'
      age: int
    
    var fname = "Mark"
    var age = 44
    
    # compiles
    
    
    
    var fname = "Mark"
    var age = 44
    
    type name = object
      fname: string   # Error: cannot use symbol of kind 'var' as a 'field'
      age: int
    
    # compilation aborted
    

It seems to me it means something is wrong with Nim's symbol lookup. Or am I 
missing something?

Reply via email to