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.

Reply via email to