
Ask HN: JS's for-of loop conceptually flawed, or is it just me? - antrion
When working with generators, two identical for-of loops don&#x27;t show the same behaviour.
Specifically, the first one will behave as expected, whereas the second one will terminate immediately.
What is this?<p>I know that the iterator `g` will signal the value `done` after the first loop, but this behaviour was unexpected and really counterintuitive to me<p>Note: contrary to this example, for-of loops of arrays will work as I expected. It just doesn&#x27;t make sense<p>Code example:<p>&gt; function* gen() { yield* [1,2,3] }<p>undefined<p>&gt; let g = gen()<p>undefined<p>&gt; for (let el of g) console.log(el)<p>1<p>2<p>3<p>undefined<p>&gt; for (let el of g) console.log(el)<p>undefined<p>edit: layout
======
tantalor
Same in python,

    
    
        >>> def gen(): yield 1; yield 2; yield 3
        ... 
        >>> g = gen()
        >>> for el in g: print el
        ... 
        1
        2
        3
        >>> for el in g: print el
        ... 
        >>>

------
detaro
You reached the end of the iterator with the first loop, so there aren't any
elements left in it to iterate over. That's consistent to how iterators work
in other languages at least.

~~~
antrion
I know that as per the iterator spec this is normal behaviour. It just seems
to me that the behaviour that follows from this is really quite strange. When
I want to be able to loop over the contents twice, how am I supposed to to
that?

~~~
detaro
Depends on what your generator does. If it just does simple calculations, just
generate a second instance of it.

Otherwise there are constructions that provide a virtual copy of an iterator
and cache the values they still need for the second loop.

Or just don't use an iterator if it doesn't fit the model you need, or turn it
into an array before.

(Part of) the idea behind generators is that you don't store all results,
because they could be a long or possibly even infinite sequence. E.g. in
Python the basic iterator is range(X), which returns the numbers from 0 to
X-1. If X=100000, it is a bad idea to generate a giant list of all those
numbers, just because you want to know how often you ran through a loop.

~~~
antrion
How would you copy it then? I have tried the npm deep-copy library, but that
didn't work (Symbol.Iterator isn't enumerable for example)

edit: I just thought, I could make a function, bind that to a variable and
regen the generator again and again

~~~
detaro
if you can easily create a new instance, that's the way to go.

