I tried to create a template that expands to multiple values during sequence initialization, eg:
template myTemplate(x: untyped) =
int(x), int(x shr 2)
var a: seq[int] = @[myTemplate(13)]
assert(a == @[13, 3])
The compiler complains, that it expected an expression, but instead found the ,. In comparison, this is easily done in C:
#define MYTEMPLATE(x) (int)(x), (int)((x)>>2)
int a[2] = { MYTEMPLATE(13) }
Is there a way to create the same in Nim?
How about ?
template myTemplate(x: untyped) : untyped =
@[int(x), int(x shr 2)]
var a: seq[int] = myTemplate(13)
assert(a == @[13, 3])
Thank you for the reply, however this is not what I want. The template should not create a sequence, but produce some elements of a sequence. A better example of what I need is:
var a: seq[int] = @[1, myTemplate(13), 2]
assert(a == @[1, 13, 3, 2])
I think that's not possible with Nim's templating system, because a template can only expand into a single NimNode, while this would require expanding into two sibling NimNodes.
Idk what you want to archieve, but how about something like this?
const lut = static:
var result: seq[int]
template entry(x: int) =
result.add(x)
result.add(x shr 2)
entry 42
entry 12
entry 6
result
Here you go:
import macros
template myTemplate(x): untyped = (x, 3)
macro flatten(x: typed): untyped =
result = newNimNode(nnkBracket, x)
for y in x:
if y.kind == nnkTupleConstr and y.len == 2:
result.add y[0]
result.add y[1]
else:
result.add y
result = newCall("@", result)
var a: seq[int] = flatten((1, myTemplate(13), 2))
assert(a == @[1, 13, 3, 2])
But the original code in C is convoluted, why replicate it.