This doesn't work:

template bar() {.dirty.} =
  echo a


template foo() =
  let a = 5
  bar()

foo()

but this does:

template bar() {.dirty.} =
  echo a


template foo() {.dirty.}  =
  let a = 5
  bar()

foo()

Is this a bug or I don't understand something about templates?

2018-01-02 20:56:33

template bar() =
  echo a

template foo() {.dirty.}  =
  let a = 5
  bar()

foo()
echo a

I would expect exactly that behaviour. As templates are hygienic by default, we need dirty pragma for foo() to make variable a visible outside.

2018-01-02 21:29:33

The {.dirty.} attribute forces template to copy-paste its code at the call side. It's typically used to make all symbols inject but it also means all the code inside of it is not symbol-checked too, it is deferred until unrolling the whole template, which effectively means it can inject its symbols not only up the hierarchy but also down it, like globals.

At least that's how I perceive the logic behind it.

2018-01-03 10:49:10
template bar() {.dirty.} =
  echo a

template foo() =
  
  let a {.inject.} = 5
  bar()

foo()
2018-01-03 11:37:09
cdome, why do you mark template bar() with dirty pragma? It is not needed in this case. 2018-01-03 16:00:15

Hi Stefan,

It is not required as you say. As I understood it, zielmicha wants to call dirty template from hygienic template.

One more potential solution.

template bar(a) {.dirty.} =
  echo a

template foo() =
  
  let a = 5
  bar(a)

foo()

2018-01-05 10:41:38

At least that's how I perceive the logic behind it.

That is exactly what happens, can we improve the manual with your explanation?

2018-01-10 08:29:04
But of course, I'd be glad.
2018-01-10 22:41:12

I think maybe this is template bug. These code doesn't compile from @zielmicha.

template bar() {.dirty.} =
  echo a


template foo() =
  let a = 5
  bar()

foo()

But when we turn foo into proc, the code works.

template bar() {.dirty.} =
  echo a


proc foo() =
  let a = 5
  bar()

foo()

So it is doesn't matter if the foo is hygienic or not.

2018-03-30 01:53:44