Templates donotation神奇地将一个否则被拒绝的表达式作为参数修复

Templates donotation神奇地将一个否则被拒绝的表达式作为参数修复,templates,nim-lang,do-notation,Templates,Nim Lang,Do Notation,在Nim模板中:作为对的后续,我想到了通过使用重载,甚至在本例中使用普通包装来解决默认参数不可用的问题。不过,如果没有什么东西再次击中风扇,那就太好了,让我分享一下: 请注意,bodyFinally现在是一个硬参数(必须指定) template tpl(x: bool, body: untyped, bodyFinally: untyped): void = if x: body else: bodyFinally # we add a convenience helper with

在Nim模板中:作为对的后续,我想到了通过使用重载,甚至在本例中使用普通包装来解决默认参数不可用的问题。不过,如果没有什么东西再次击中风扇,那就太好了,让我分享一下:

请注意,
bodyFinally
现在是一个硬参数(必须指定)

template tpl(x: bool, body: untyped, bodyFinally: untyped): void =
  if x: body
  else: bodyFinally

# we add a convenience helper with 2 args here.
template tpl2(x: bool, body: untyped): void =
  tpl(x) do:
    body
  do:
    discard

#call site:
var r: int
tpl2(true) do:
  r = 2
酷(它工作)。虽然这不是我第一次尝试使用tpl2;这是:

template tpl2(x: bool, body: untyped): void =
  tpl(x, body, discard)
因为这就是
所做的
应该重写的事情。除了我们得到:

错误:应为表达式,但找到“关键字放弃”


那么这是怎么回事?

解释原因有点复杂,但您可以这样编写重载:

template tpl(x: bool, body: untyped, bodyFinally: untyped) =
  if x: body
  else: bodyFinally

template tpl(x: bool, body: untyped): void =
  tpl(x, body, (discard))

var r = 1

tpl(false):
  r = 2

echo r

tpl(true):
  r = 3

echo r
额外的括号触发一个特殊的解析规则,生成
nkStmtListExpr
AST节点,该节点是此处模板的有效输入。此构造通常用于C样式的if语句中,该语句包含赋值和空测试:

if (let f = fopen(...); f != 0):
  # do something with `f`
正如预期的那样,运行上述程序的输出将是:

1
3

解释原因有点复杂,但您可以这样编写重载:

template tpl(x: bool, body: untyped, bodyFinally: untyped) =
  if x: body
  else: bodyFinally

template tpl(x: bool, body: untyped): void =
  tpl(x, body, (discard))

var r = 1

tpl(false):
  r = 2

echo r

tpl(true):
  r = 3

echo r
额外的括号触发一个特殊的解析规则,生成
nkStmtListExpr
AST节点,该节点是此处模板的有效输入。此构造通常用于C样式的if语句中,该语句包含赋值和空测试:

if (let f = fopen(...); f != 0):
  # do something with `f`
正如预期的那样,运行上述程序的输出将是:

1
3