Here is a link to some recent discussion and links to for loop macros that may simplify your life.
The manual has actually already been updated to include this, but I don't know if the "devel" HTML is online anywhere.
Thanks for the pointer.
From a programmer's point of view: Generators (iterators) and recursion are central features of all modern programming languages. They should not be limited unnecessarily.
Generators/iterators should have all benefits of a normal procedure (i.e. allow for forward declarations, recursion, being passable to another proc/iterator, allowing for premature exit with 'return') The only difference between a generator/iterator and a procedure should be that a generator maintains some data between calls.
The argument of "being inlined currently" doesn't convince me. The compiler should find out itself if it can inline a given iterator or not, and if it needs some sort of closure. It's not the responsibility of the programmer to add a 'closure' pragma.
Here is my example
import strutils, sequtils
import macros
{.experimental: "forLoopMacros".}
macro toItr*(x : ForLoopStmt): untyped =
let expr = x[0]
let call = x[1][1] # Get foo out of tolItr(foo)
let body = x[2]
result = quote do:
block:
let itr = `call`
for `expr` in itr():
`body`
iterator firstn(g:iterator():int, n:int): int =
for i in 0..<n :
yield g()
proc fibonacci(): iterator(): int =
result = iterator(): int =
var a, b : int
a = 0; b= 1
while true:
yield a
(a, b) = (b, a + b)
for x in firstn(toItr(fibonacci()), 10) :
echo x
So, I get this is example code, but your fibonacci has no parameters. That makes it not a very good match for a closure iterator factory proc in the first place. Maybe if it did you could do your composition "inside" fibonacci instead. E.g.:
proc fibonacci(its = 0): iterator(): int =
result = iterator(): int =
var a = 0
var b = 1
for i in 1..its:
yield a
(a, b) = (b, a + b)
for x in toItr(fibonacci(10)):
echo x
Also, as of nim-1.4 you no longer need {.experimental: "forLoopMacros".}. Also, if you put "Nim" after the triple backtick open quote the code block will be rendered colorized like mine above.
That said, yes, for loop macros may not quite have the syntactic compositional properties you want. { or a dot-call either which I think they should maybe grow, as in for x in fibonacci(10).toItr: .... } One usually gets further doing PRs or RFCs in Nimland than just requesting (or worse demanding) features, though.
Anyway, you may have a little bit of thinking/transforming to do on that 300 line Python iterator, but I'll bet you can get something not too ugly with some work.
Thanks for your comments. Currently I don't have enough experience in Nim - I am still learning. And since I am still convinced that iterators should upgrade from second class citizens to first class citizens in Nimland, tricky macros are not a solution.
For a pull request concerning the compiler I would have to acquire a lot of expertise in Nim's compiler's internals. And I have seen very convincing pull requests which have a hard time to get accepted. This is not at all encouraging.
I have to say, @HJarausch, you started this thread looking for a "recommended workaround'. I feel like we gave you a pretty good, if limited, one. Now you are "moving the goalposts" (shifting criteria for 'success') towards having iterators with each & every feature of Python's just to be deemed "first class". (Python itself took decades to grow those features.)
Some thinking/re-thinking/code re-org will always be necessary moving code from Python to Nim. A 300 line recursive iterator does sound tricky, and honestly kind of a challenging way to "dip your toes" in the water of Nim. Maybe that was the point, but then if you feel you are in "too deep", perhaps you should look for something simpler?
For example, if that 300 line iterator is too slow, maybe it is not "the iteration itself" which is slow, but calculations done within it? There are"bridges" to Python, like nimpy, where you can just write modules in Nim for direct import into Python. So, if just speeding it up is your ultimate goal as a Nim experiment then you might be able to just re-write some of the more expensive "sub-iterator" computation in Nim. Good luck!