I found the strange behavior related to iterator. In the following code, iterator "greater" iterates over all integer greater than a and less than 10. Then, put this iterator to an object S. Now, call these iterators two times. First one ("test by iterator") works well. But second one("test by iterator member") woks only first iteration. The output would be
test by iterator
3 4 5 6 7 8 9
6 7 8 9
test by iterator member
3 4 5 6 7 8 9
Is it a bug?
type S = object
greater:iterator(a:int):int
iterator greater(a:int):int {.closure.} =
for i in a + 1 ..< 10:yield i
var s = S(greater:greater)
# works well
echo "test by iterator"
for i in greater(2): stdout.write i, " "
echo ""
for i in greater(5): stdout.write i, " "
echo ""
# not work second for loop
echo "test by iterator member"
for i in s.greater(2): stdout.write i, " "
echo ""
for i in s.greater(5): stdout.write i, " "
echo ""
It's not overly weird behaviour, your closure.finished is true, and when iterating over closures the for loop is practically just the following. Running this code shows that the closure is finished and needs reset.
while not closure.finished:
let i = closure(state)
Thanks! Then, how to reset closure? I searched Nim manual, but I couldn't find...
By the way, I also tried non-closure member iterator like the following. But complication fails. So, I used closure. Are there any way? I think I should write some pragma in the object definition.
type S = object
greater:iterator(a:int):int
iterator greater(a:int):int =
for i in a + 1 ..< 10:yield i
var s = S(greater:greater)
There is no way to reset it but you can create a new one:
type S = object
greater:iterator(a:int):int
iterator greater(a:int):int {.closure.} =
for i in a + 1 ..< 10:yield i
var s = S(greater:greater)
echo "test by iterator member"
for i in s.greater(2): stdout.write i, " "
s = S(greater: greater)
echo ""
for i in s.greater(5): stdout.write i, " "
echo ""
I also noticed
s.greater = greater kind of resets it again