模板表达式的默认参数

时间:2018-04-02 14:19:00

标签: templates nim default-arguments

如果我想创建一个可以接受2个untyped参数的模板,并通过do表示法传递它们,那么当我省略第二个do时,我想要一种以参数的默认值的形式指定回退的方法。就这样:

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

#call site:
var r: int
tpl(true) do:
  r = 2
do:
  raise newException(Exception, "")

这有效,但是:

template tpl(x: bool, body: untyped, bodyFinally: untyped = discard): void =
  # same rest
  

错误:预期表达式,但找到'关键字丢弃'

不接受默认值,并且消息很奇怪,discard表达式不是。

尝试解决方法:

template tpl(x: bool, body: untyped, bodyFinally: untyped = proc()): void =
  # same rest

然后我们得到:

  

错误:表达式' proc()'属于'类型proc(){。closure。}'和   必须被丢弃

我已经适度地接受了这一点,即使我发现这个discard要求毫无用处,并且语言令人讨厌,因为它迫使我们在通用代码中加入令人不舒服的体操这里。

让我们再次编辑:

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

现在的结果是:

  

错误:内部错误:expr(nkProcTy);未知节点类型

1 个答案:

答案 0 :(得分:3)

确实没有办法将代码块描述为默认参数值。有两种可能的解决方法:

1)您可以通过重载来模拟默认值:

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

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

第二个重载的另一个较短版本是:

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

2)您可以使用可在模板中检测到的默认值nil

import macros

template tpl(x: bool, body: untyped, bodyFinally: untyped = nil) =
  if x:
    body
  else:
    when astToStr(bodyFinally) == "nil":
      discard
    else:
      bodyFinally

请注意,我必须使用astToStr,因为当用户提供非默认值时,无法将bodyFinallynil进行比较。