I'm also with the "use the least powerful construct that suits your need".
Also be aware that templates literaly replace your code, so you might duplicate your computation and side-effects. Test-case:
template echo_twice(a: int) =
echo a
echo a
proc plus_one(a: int): int =
echo "bar input: " & $a
result = a + 1
echo_twice(1.plus_one)
Result:
bar input: 1
2
bar input: 1
2
With an inline proc:
proc echo_twice(a: int) {.inline.}=
echo a
echo a
proc plus_one(a: int): int =
echo "bar input: " & $a
result = a + 1
echo_twice(1.plus_one)
Result
bar input: 1
2
2
So if the input is used several time inside the template you should assign it to a temporary variable.
Spawning off to a proc vs template question for another code..
In a PR to a Nim package fab, I used templates instead of procs liberally. Would procs have been preferred there?
Yes, you should only use templates if they are really needed, i.e. the concept that @mratsim mentioned: "use the least powerful construct that suits your need"
I don't think templates are really needed for that code.
I do not really understand the initial question.
But whenever you recommend using procs instead of templates, do not forget my observation that multiple proc calls with same argument are not optimized:
See
templates would have the same issue.
The initial question is about inline procs vs templates.
templates would have the same issue.
I had the hope that templates would benefit from "Common subexpression elimination".
I think that such an optimization could only be performed if the effects system were pervasive. Only purely mathematical functions could be used this way, and that means no I/O or state. I suppose it was never a priority.
Are there applications that could really benefit? Perhaps that could be an optimization...
GCC/Clang will do Common Sub-Expression Elimination and Constant Folding if it can prove that it's safe (usually for primitive operations on primitive types or realizing that there are memory initialization that are unneeded on stack object).
With inline procs and templates, it's easier because they don't have a function call indirection.