Just FYI, I noticed that overloading via parameter constraints also work as an evalOnce alternative
|
macro evalOnceAs*(exp, alias: untyped): untyped = |
|
## Ensure that `exp` is evaluated only once unless it is a symbol in which |
|
## case it's used directly. |
|
## |
|
## A common case where this is useful is template parameters which, when |
|
## an expression is passed in, get evaluated multiple times. |
|
## |
|
## Based on a similar macro in std/sequtils |
|
expectKind(alias, nnkIdent) |
|
|
|
let |
|
body = nnkStmtList.newTree() |
|
val = |
|
if exp.kind == nnkSym: |
|
# The symbol can be used directly |
|
# TODO dot expressions? etc.. |
|
exp |
|
else: |
|
let val = genSym(ident = "evalOnce_" & $alias) |
|
body.add newLetStmt(val, exp) |
|
val |
|
body.add( |
|
newProc( |
|
name = genSym(nskTemplate, $alias), |
|
params = [getType(untyped)], |
|
body = val, |
|
procType = nnkTemplateDef, |
|
) |
|
) |
|
|
|
body |
vs
https://github.com/mratsim/tattletale/blob/5555745/workspace/libtorch/src/tensors.nim#L755-L766
template `[]`*(t: Tensor{call}, args: varargs[untyped]): untyped =
let tmp = t
convertLibTorchExceptions:
wrapTorchTensor:
tmp.raw[args]
template `[]`*(t: Tensor{`let`|`var`|`const`|lvalue|param}, args: varargs[untyped]): untyped =
convertLibTorchExceptions:
wrapTorchTensor:
t.raw[args]
Though it's true that I didn't try with sym constraint, I'm not sure if it works in untyped templates.
Just FYI, I noticed that overloading via parameter constraints also work as an evalOnce alternative
nim-stew/stew/evalonce.nim
Lines 12 to 42 in 30dadcd
vs
https://github.com/mratsim/tattletale/blob/5555745/workspace/libtorch/src/tensors.nim#L755-L766
Though it's true that I didn't try with sym constraint, I'm not sure if it works in untyped templates.