I try to write a template, which takes a code: stmt and returns an expr, or more specifically a float. However, I cannot find a way to use such a template. For instance:
template runTimed*(code: stmt): expr {.immediate.} =
let s = cpuTime()
code
let e = cpuTime()
e-s
let time = runTimed:
# ... anything ...
var x = 0.0
for i in 1 .. 1000000:
x += x * i.toFloat
This produces a "wrong number of arguments". The only way I could get it to work was to not return anything from the template. Does this mean that it is not possible in general to have templates with a code block that return something? Or am I just doing something wrong?
Update: What does work is to use an into: expr, which circumvents "returning" and, as a result, looks a bit weird. I'm still wondering if returning is possible here?
A simple do fixes it: http://nim-lang.org/docs/manual.html#procedures-do-notation
import times
template runTimed*(code: stmt): expr {.immediate.} =
let s = cpuTime()
code
let e = cpuTime()
e-s
let time = runTimed do:
var x = 0.0
for i in 1 .. 1000000:
x += x * i.toFloat
Awesome, thanks! I actually was aware of do notation but the manual suggests that it only works for proc and not for a general stmt. Does using a do here mean that the stmt is in fact passed differently, i.e., is it converted to a closure first?
Since it works for templates as well, I now can also answer another question that was always bothering me -- how to pass multiple blocks to a template:
template twoBlocks(cond: bool, code1: stmt, code2: stmt): stmt {.immediate.} =
if cond:
code1
else:
code2
twoBlocks(false) do:
echo "First"
do:
echo "Second"
@yglukhov: Is using do notation with templates a new feature or why does issue #2106 not mention this solution?