default arguments to template's expressions

隐身守侯 提交于 2019-12-11 14:58:37

问题


If I want to make a template that can accept 2 untyped arguments, and pass them through do notation, when I omit the second do I'd like to have a way to specify a fallback in the form of a parameter's default value. as such:

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, "")

This works, but that:

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

Error: expression expected, but found 'keyword discard'

The default value is not accepted, and the message is weird, discard is an expression isn't it.

Attmpts to workaround:

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

Then we get:

Error: expression 'proc ()' is of type 'type proc (){.closure.}' and has to be discarded

I'm moderately ready to accept that, even though I find this discard requirement uselessly pedant, and a nuisance of the language, since it's forcing us into uncomfortable gymnastics in generic code like here.

let's edit again:

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

And now the result is:

Error: internal error: expr(nkProcTy); unknown node kind


回答1:


It's true that there is no way to describe a block of code as a default parameter value. There are two possible work-arounds for this:

1) You can simulate the default values through an overload:

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

Another shorter version of the second overload would be this:

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

2) You can use a default value like nil that can be detected inside the template:

import macros

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

Please note that I had to use astToStr, because it won't be possible to compare bodyFinally to nil when the user supplies a non-default value.



来源:https://stackoverflow.com/questions/49613003/default-arguments-to-templates-expressions

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!