Search code examples
javascriptiteratoryield

for..of and the iterator state


Consider this python code

it = iter([1, 2, 3, 4, 5])

for x in it:
    print x
    if x == 3:
        break

print '---'

for x in it:
    print x

it prints 1 2 3 --- 4 5, because the iterator it remembers its state across the loops. When I do seemingly the same thing in JS, all I get is 1 2 3 ---.

function* iter(a) {
    yield* a;
}

it = iter([1, 2, 3, 4, 5])

for (let x of it) {
    console.log(x)
    if (x === 3)
        break
}

console.log('---')

for (let x of it) {
    console.log(x)
}

What am I missing?


Solution

  • As pointed out in other answers, for..of closes the iterator in any case, so there's another wrapper necessary to preserve the state, e.g.

    function iter(a) {
        let gen = function* () {
            yield* a;
        }();
    
        return {
            next() {
                return gen.next()
            },
            [Symbol.iterator]() {
                return this
            }
        }
    }
    
    
    it = iter([1, 2, 3, 4, 5]);
    
    for (let x of it) {
        console.log(x);
        if (x === 3)
            break;
    }
    
    console.log('---');
    
    for (let x of it) {
        console.log(x);
    }