Почему грязная инъекция необходима даже для кода в рамках шаблона?

Пожалуйста, обратите внимание на следующее:

import options

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

discard
  tpl[int]:
    echo b

Это строит и запускает и приводит к выводу:

4

Но если вы удалите прагму {.inject.}, вы получите:

...шаблон/общий экземпляр отсюда
Ошибка: необъявленный идентификатор: 'b'

Я не думаю, что мы можем считать блок кода echo b чуждым «внутренностям» шаблона, поскольку: он используется только в расширенном виде внутри шаблона и: он передается как аргумент, а не используется снаружи.

Я вынужден использовать что-то грязное, и теперь я загрязнил свою глобальную область видимости, чтобы заставить это работать?


person v.oddou    schedule 31.03.2018    source источник


Ответы (2)


То, как это работает, имеет смысл. Вы хотите четко указать, что доступно внутри кода, указанного пользователем.

Вы можете сохранить глобальную область видимости гигиеничной, используя block:

import options

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

discard
  tpl[int]:
    echo b
person dom96    schedule 01.04.2018
comment
Я не уверен, что это имеет смысл. Я думал, что инъекция предназначена для того, чтобы сделать что-то общедоступным в пределах возможностей вызывающего. В данном случае такой необходимости нет. - person v.oddou; 01.04.2018

Причина в том, что введенные имена являются частью общедоступного интерфейса шаблона. Вы не хотите, чтобы детали реализации шаблона просачивались внутрь пользовательского кода и, возможно, создавали там конфликты имен, поэтому все переменные, созданные внутри шаблона, по умолчанию скрыты от пользовательского кода.

Использование inject таким образом не считается грязным, здесь это правильно.

person zah    schedule 01.04.2018