Search code examples
templatesnim-langhygiene

Why dirty injection is necessary even for code within template's scope?


Please consider the following:

import options

template tpl[T](a: untyped) : Option[T] =
  var b {.inject.}: T = 4
  a
  none(int)

discard
  tpl[int]:
    echo b

This builds and runs and results in output:

4

But, if you remove the {.inject.} pragma, you get:

...template/generic instantiation from here
Error: undeclared identifier: 'b'

I don't think we can consider the block of code echo b foreign to the "insides" of the template since: it's only used expanded withing the template, and: it's passed as an argument, not used outside.

I'm forced to use something dirty and now I've dirtied my global scope to make this work ?


Solution

  • The way this works makes sense. You want to be explicit about what is available inside the code specified by the user.

    You can keep your global scope hygienic by using block:

    import options
    
    template tpl[T](a: untyped) : Option[T] =
      block:
        var b {.inject.}: T = 4
        a
        none(int)
    
    discard
      tpl[int]:
        echo b