In Nim templates: as a follow-up from this problem, I had the idea of working around the default-argument unavailability by using overloading, or even in this case, plain wrapping. Though, it would be too good if something didn't hit the fan again, let me share:
Notice that bodyFinally
is now a hard (must specify) argument.
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
cool (it works). Though this was not my first shot for tpl2
; this was:
template tpl2(x: bool, body: untyped): void =
tpl(x, body, discard)
Because that's what do
supposedly rewrites the thing anyway. Except we get:
Error: expression expected, but found 'keyword discard'
So what's up with that ?
It's a bit complicated to explain why, but you could have written the overload like this:
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
The extra brackets trigger a special parsing rule producing nkStmtListExpr
AST node, which is a valid input for the template here. This construct is usually used in C-style if statements that include an assignment followed by a NULL-test:
if (let f = fopen(...); f != 0):
# do something with `f`
As expected, the output of running the above program will be:
1
3