You don't need macros at all.
Here is what you really wanted to do:
proc fibo(a, b: int): iterator: int =
iterator inner: int =
var
a = a
b = b
while true:
yield a
(a, b) = (b, a+b)
inner
let x = fibo
for _ in 1 .. 5:
echo x(1, 1)()
echo x(10, 20)()
echo x(100, 999)()
echo "\n##########\n"
let
y = fibo
z = y(5, 8)
for i in 1 .. 5:
echo z()
The problem you encountered is the bizarre semantics of assignment of
iterators. In fact, let x = fibo actually created a new _object_ of iterator.
When it passed through var a = a; var b = b, changing parameters a and b won't
change anything. You can check it does if you don't shadow the arguments:
iterator fibo(a, b: int): int {.closure.} =
var
c = a
d = b
while true:
yield a
(c, d) = (b, a+b)
let x = fibo
for _ in 1 .. 5:
echo x(1, 1)
echo x(10, 20) # here the result is different
echo x(100, 999)
All in all: an iterator is an _object_. When you "call" it, you change it's
fields' (arguments') values and resume its the execution from last yield to the
next one. If you wanted a NEW object when you call with different arguments,
what you should return is an iterator.
The problem with Nim's iterator is that sometimes "iterator" means a procedure
which creates a new iterator (the one you declare with "iterator" keyword),
sometimes an object the said procedure returns and sometimes both inlined into
a loop.