如何在模板钩子中使用闭包参数?
How to use a closure parameter in a template hook?
我有以下代码定义:
type Tree* = ref ...
type Parser* = ref object
hooks: Table[string, proc(it: var Tree)]
template hook*(this: var Parser, rule: string, body: untyped) =
this.hooks[rule] = proc(it: var Tree) =
body
但是我在尝试使用它时遇到错误 "Error: undeclared identifier: 'it'":
let gp: Parser = ...
gp.hook("Value"):
echo $it
我希望将其翻译成:
gp.hooks["Value"] = proc(it: var Tree) =
echo $it
这很好用。
好的,我找到了解决方案:
template hook*(this: var Parser, rule: string, body: untyped) =
this.hooks[rule] = proc(tree: var Tree) =
var it {.inject.} = tree
body
但这出乎意料,因为 'it' 已经在范围内!
模板中的变量、类型、形式参数和其他内容在默认情况下是生成符号的。 gensym
表示生成保证唯一的符号,以避免模板外的名称冲突。
您可以通过以下示例了解它是如何生成的:
template mkproc() =
proc foo(it: var Tree) =
echo it
mkproc()
foo()
这会给你这个编译错误:
Error: type mismatch got <> but expected one of:
proc foo(it`gensym123456: var Tree)
其中 it
确实是 gensym'd。
要修复 hook
,就像您的解决方案一样,是用 {.inject.}
标记变量,因为无法标记参数。
template hook*(this: var Parser, rule: string, body: untyped) =
this.hooks[rule] = proc(it: var Tree) =
var it {.inject.} = it
body
最后,像 hook
这样使用的模板可以受益于 {.dirty.}
。这会将所有符号标记为 {.inject.}
,包括 proc 参数。
template hook*(this: var Parser, rule: string, body: untyped) {.dirty.} =
this.hooks[rule] = proc(it: var Tree) =
body
parser.hook "rule":
echo it
我有以下代码定义:
type Tree* = ref ...
type Parser* = ref object
hooks: Table[string, proc(it: var Tree)]
template hook*(this: var Parser, rule: string, body: untyped) =
this.hooks[rule] = proc(it: var Tree) =
body
但是我在尝试使用它时遇到错误 "Error: undeclared identifier: 'it'":
let gp: Parser = ...
gp.hook("Value"):
echo $it
我希望将其翻译成:
gp.hooks["Value"] = proc(it: var Tree) =
echo $it
这很好用。
好的,我找到了解决方案:
template hook*(this: var Parser, rule: string, body: untyped) =
this.hooks[rule] = proc(tree: var Tree) =
var it {.inject.} = tree
body
但这出乎意料,因为 'it' 已经在范围内!
模板中的变量、类型、形式参数和其他内容在默认情况下是生成符号的。 gensym
表示生成保证唯一的符号,以避免模板外的名称冲突。
您可以通过以下示例了解它是如何生成的:
template mkproc() =
proc foo(it: var Tree) =
echo it
mkproc()
foo()
这会给你这个编译错误:
Error: type mismatch got <> but expected one of:
proc foo(it`gensym123456: var Tree)
其中 it
确实是 gensym'd。
要修复 hook
,就像您的解决方案一样,是用 {.inject.}
标记变量,因为无法标记参数。
template hook*(this: var Parser, rule: string, body: untyped) =
this.hooks[rule] = proc(it: var Tree) =
var it {.inject.} = it
body
最后,像 hook
这样使用的模板可以受益于 {.dirty.}
。这会将所有符号标记为 {.inject.}
,包括 proc 参数。
template hook*(this: var Parser, rule: string, body: untyped) {.dirty.} =
this.hooks[rule] = proc(it: var Tree) =
body
parser.hook "rule":
echo it