【问题标题】:default arguments to template's expressions模板表达式的默认参数
【发布时间】:2018-04-02 14:18:59
【问题描述】:

如果我想制作一个可以接受 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 ()' 的类型为 'type proc (){.closure.}' 并且 必须丢弃

我已经准备好接受这一点,尽管我发现这个 discard 要求毫无用处,而且是语言的麻烦,因为它迫使我们在像这里这样的通用代码中进行不舒服的体操。

让我们再次编辑:

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

现在结果是:

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

【问题讨论】:

    标签: templates nim-lang default-arguments


    【解决方案1】:

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

    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 进行比较。

    【讨论】:

    • 不可以用when bodyFinally is nil或者when compiles(bodyFinally == nil)吗?
    • nil 不是类型,因此不能与is 运算符一起使用。您可能会发现这违反直觉,但对于编译器而言,compilesastToStr 更昂贵(因为它涉及执行编译器的整个语义传递,而 astToStr 是对 AST 树的简单遍历。
    • 非常有趣。 python 的is 可以做“is Null”或“is not Null”,这就是为什么我需要让我的想法适应is 在 Nim 中的含义。还要感谢astToStr 的技巧,这是黄金建议。答案已接受
    猜你喜欢
    • 1970-01-01
    • 2021-02-04
    • 1970-01-01
    • 2013-02-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多