The title is the last sentence from the https://nim-lang.org/docs/tut2.html#templates and it refers to the following snippet of code:
template withFile(f: untyped, filename: string, mode: FileMode,
body: untyped): typed =
let fn = filename
var f: File
if open(f, fn, mode):
try:
body
finally:
close(f)
else:
quit("cannot open: " & fn)
withFile(txt, "ttempl3.txt", fmWrite):
txt.writeLine("line 1")
txt.writeLine("line 2")
I can see fn is used in if open(f, fn, mode): and in quit("cannot open: " & fn). But why would it be evaluated twice if we did not use let? Aren't arguments for template immutable?
Interesting question. We can easily prove that the statement from tutorial is correct:
main()
$ ./t
str proc called
strprocresult
str proc called
strprocresult
So indeed not a plain string is passed to the template, but the passed expression is called inside of template. I think for typed or untyped arguments we may expect that, but maybe not for real data types like string? I guess one of the Nim devs will write some words of explanations later.
Templates use a simple substitution mechanism, besides the fact that you don't have to care about putting your arguments in () (see C's preprocessor), it's quite comparable to what C's preprocessor does.
That makes sense, thanks!