Skip to content

evalOnce alternative #272

Description

@mratsim

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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions