为什么即使对于模板范围内的代码也需要脏注入?
Why dirty injection is necessary even for code within template's scope?
请考虑以下事项:
import options
template tpl[T](a: untyped) : Option[T] =
var b {.inject.}: T = 4
a
none(int)
discard
tpl[int]:
echo b
这将构建并运行并产生输出:
4
但是,如果您删除 {.inject.}
pragma,您会得到:
...template/generic instantiation from here
Error: undeclared identifier: 'b'
我认为我们不能认为代码块 echo b
与模板的 "insides" 无关,因为:它仅在模板中扩展使用,并且:它作为参数传递, 不在外面使用。
我被迫使用一些脏东西,现在我已经弄脏了我的全局范围来完成这项工作?
这种工作方式很有意义。您想明确说明用户指定的代码中可用的内容。
您可以使用 block
:
来保持全局范围的卫生
import options
template tpl[T](a: untyped) : Option[T] =
block:
var b {.inject.}: T = 4
a
none(int)
discard
tpl[int]:
echo b
原因是注入的名称是模板 public 接口的一部分。您不希望模板的实现细节泄露到用户代码中并可能在那里造成命名冲突,因此默认情况下,在模板中创建的所有变量都对用户代码隐藏。
像这样使用inject
不被认为是肮脏的,这是正确的做法。
请考虑以下事项:
import options
template tpl[T](a: untyped) : Option[T] =
var b {.inject.}: T = 4
a
none(int)
discard
tpl[int]:
echo b
这将构建并运行并产生输出:
4
但是,如果您删除 {.inject.}
pragma,您会得到:
...template/generic instantiation from here
Error: undeclared identifier: 'b'
我认为我们不能认为代码块 echo b
与模板的 "insides" 无关,因为:它仅在模板中扩展使用,并且:它作为参数传递, 不在外面使用。
我被迫使用一些脏东西,现在我已经弄脏了我的全局范围来完成这项工作?
这种工作方式很有意义。您想明确说明用户指定的代码中可用的内容。
您可以使用 block
:
import options
template tpl[T](a: untyped) : Option[T] =
block:
var b {.inject.}: T = 4
a
none(int)
discard
tpl[int]:
echo b
原因是注入的名称是模板 public 接口的一部分。您不希望模板的实现细节泄露到用户代码中并可能在那里造成命名冲突,因此默认情况下,在模板中创建的所有变量都对用户代码隐藏。
像这样使用inject
不被认为是肮脏的,这是正确的做法。