Iterators and Generators
Manual Iterators
Build a small object with a next method.
manual-iterator
An iterator returns one result at a time. Each call to `next` gives a value and a `done` flag.
Manual Iterators
manual_iterator.js
Replay: real traced execution (multi-file project)
const limit = 3;
let current = 1;
const values = [];
let value = null;
let done = false;
const iterator = {
next() {
if (current <= limit) {
const value = current;
current = current + 1;
return { value, done: false };
}
return { value: null, done: true };
},
};
({ value, done } = iterator.next());
while (!done) {
values.push(value);
({ value, done } = iterator.next());
}
console.log("limit=" + limit);
console.log("values=" + values.join(","));
const limit = 2;
let current = 1;
const values = [];
let value = null;
let done = false;
const iterator = {
next() {
if (current <= limit) {
const value = current;
current = current + 1;
return { value, done: false };
}
return { value: null, done: true };
},
};
({ value, done } = iterator.next());
while (!done) {
values.push(value);
({ value, done } = iterator.next());
}
console.log("limit=" + limit);
console.log("values=" + values.join(","));
const limit = 4;
let current = 1;
const values = [];
let value = null;
let done = false;
const iterator = {
next() {
if (current <= limit) {
const value = current;
current = current + 1;
return { value, done: false };
}
return { value: null, done: true };
},
};
({ value, done } = iterator.next());
while (!done) {
values.push(value);
({ value, done } = iterator.next());
}
console.log("limit=" + limit);
console.log("values=" + values.join(","));
limit ← 3, current ← 1, values ← (empty), value ← null, done ← false
1const limit→ 3 = 3; //@limit=2, 42let current→ 1 = 1;3const values→ (empty) = [];4let value→ null = null;5let done→ false = false;67const iterator→ [object Object] = {8 next() {9 if (current <= limit) {10 const value = current;11 current = current + 1;12 return { value, done: false };13 }14 return { value: null, done: true };15 },16};1718({ value, done } = iterator[object Object].next());19while (!done) {values ← 1
pass 1 of 318({ value, done } = iterator.next());19while (!donefalse) {20 values.push(value1);21 ({ value, done } = iterator[object Object].next());22}values this step(empty) → 1valuesAll 3 passes — pass 1 is the card above pass valuevalues1 1 (empty) → 1 2 2 1 → 1,2 3 3 1,2 → 1,2,3 console.log("limit=" + limit);
21 ({ value, done } = iterator.next());22}2324console.log("limit=" + limit3);25console.log("values=" + values1,2,3.join(","));outputlimit=3 values=1,2,3
limit ← 2, current ← 1, values ← (empty), value ← null, done ← false
1const limit→ 2 = 2;2let current→ 1 = 1;3const values→ (empty) = [];4let value→ null = null;5let done→ false = false;67const iterator→ [object Object] = {8 next() {9 if (current <= limit) {10 const value = current;11 current = current + 1;12 return { value, done: false };13 }14 return { value: null, done: true };15 },16};1718({ value, done } = iterator[object Object].next());19while (!done) {values ← 1
pass 1 of 218({ value, done } = iterator.next());19while (!donefalse) {20 values.push(value1);21 ({ value, done } = iterator[object Object].next());22}values this step(empty) → 1valuesvalues ← 1,2
pass 2 of 218({ value, done } = iterator.next());19while (!donefalse) {20 values.push(value2);21 ({ value, done } = iterator[object Object].next());22}values this step1 → 1,2valuesconsole.log("limit=" + limit);
21 ({ value, done } = iterator.next());22}2324console.log("limit=" + limit2);25console.log("values=" + values1,2.join(","));outputlimit=2 values=1,2
limit ← 4, current ← 1, values ← (empty), value ← null, done ← false
1const limit→ 4 = 4;2let current→ 1 = 1;3const values→ (empty) = [];4let value→ null = null;5let done→ false = false;67const iterator→ [object Object] = {8 next() {9 if (current <= limit) {10 const value = current;11 current = current + 1;12 return { value, done: false };13 }14 return { value: null, done: true };15 },16};1718({ value, done } = iterator[object Object].next());19while (!done) {values ← 1
pass 1 of 418({ value, done } = iterator.next());19while (!donefalse) {20 values.push(value1);21 ({ value, done } = iterator[object Object].next());22}values this step(empty) → 1valuesAll 4 passes — pass 1 is the card above pass valuevalues1 1 (empty) → 1 2 2 1 → 1,2 3 3 1,2 → 1,2,3 4 4 1,2,3 → 1,2,3,4 console.log("limit=" + limit);
21 ({ value, done } = iterator.next());22}2324console.log("limit=" + limit4);25console.log("values=" + values1,2,3,4.join(","));outputlimit=4 values=1,2,3,4
Follow the Calls
limitstarts at3, andcurrentstarts at1.- Each
iterator.next()call returns an object withvalueanddone. - The loop pushes each value while
doneisfalse. - When
currentbecomes4, the next call returnsvalue: nullanddone: true. - The loop stops and prints
values=1,2,3. | call | returned value | returned done | loop action | | ---: | --- | --- | --- | | 1 | 1 | false | push 1 | | 2 | 2 | false | push 2 | | 3 | 3 | false | push 3 | | 4 | null | true | stop |
Exercise: manual_iterator.js
Reproduce limit=3 and values=1,2,3, then use the pinned limits 2 and 4 to predict values=1,2 and values=1,2,3,4.