Wasteland
Wasteland

Reputation: 5379

JS: generator has a default step while in a loop

I have a generator function with an optional max value argument. My generator function:

function* numGen(start: number, stop?: number) {
    let n = start;
    if (stop) {
        while (n < stop) {
            const step: number = yield n;
            if (step) {
                n += step;
              } else {
                n++
              }
        }
    } else {
        while(true) {
            const step: number = yield n;
            if (step) {
                n += step;
              } else {
                n++
              }
        }
    }
}

const genObj = numGen(0, 15);

Running it with just a manual call works fine:

console.log(genObj.next())
console.log(genObj.next())
...

It logs it as expected:

{ value: 0, done: false }
{ value: 1, done: false }
{ value: 2, done: false }
{ value: 3, done: false }
{ value: 4, done: false }
{ value: 5, done: false }
{ value: 6, done: false }
{ value: 7, done: false }
{ value: 8, done: false }
{ value: 9, done: false }
{ value: 10, done: false }
{ value: 11, done: false }
{ value: 12, done: false }
{ value: 13, done: false }
{ value: 14, done: false }
{ value: undefined, done: true }
{ value: undefined, done: true }
{ value: undefined, done: true }
{ value: undefined, done: true }
{ value: undefined, done: true }

The same happens when it's done with a step. All works as expected:

let s = 3;
console.log(genObj.next(s))
console.log(genObj.next(s))
console.log(genObj.next(s))
console.log(genObj.next(s))
console.log(genObj.next(s))
console.log(genObj.next(s))
console.log(genObj.next(s))
console.log(genObj.next(s))
console.log(genObj.next(s))

Outputs:

{ value: 0, done: false }
{ value: 3, done: false }
{ value: 6, done: false }
{ value: 9, done: false }
{ value: 12, done: false }
{ value: undefined, done: true }
{ value: undefined, done: true }
{ value: undefined, done: true }
{ value: undefined, done: true }

The moment I try to run it in a while loop, there seems to be some hidden/implicit step value added on top. No explicit step:

while (genObj.next().done !== true) {
    console.log(genObj.next())
}

Outputs:

{ value: 1, done: false }
{ value: 3, done: false }
{ value: 5, done: false }
{ value: 7, done: false }
{ value: 9, done: false }
{ value: 11, done: false }
{ value: 13, done: false }
{ value: undefined, done: true }

Explicit step:

let s = 3;

while (genObj.next(s).done !== true) {
    console.log(genObj.next(s))
}

Outputs:

{ value: 3, done: false }
{ value: 9, done: false }
{ value: undefined, done: true }

Upvotes: 0

Views: 61

Answers (1)

Bergi
Bergi

Reputation: 664630

You're calling genObj.next() twice in each iteration. You want to use

for (let iterResult; !(iterResult = genObj.next()).done; ) {
    console.log(iterResult)
}

Upvotes: 2

Related Questions