Iterators and Generators
Lazy Take Model
Stop consuming a generator after enough values.
lazy-take-model
A generator can describe a longer sequence while the caller decides how many values to read.
Lazy Take Model
lazy_take_model.js
Replay: real traced execution (multi-file project)
const take = 2;
const values = [];
function* squares() {
let current = 1;
while (current <= 5) {
yield current * current;
current = current + 1;
}
}
for (const value of squares()) {
if (values.length >= take) {
break;
}
values.push(value);
}
console.log("take=" + take);
console.log("values=" + values.join(","));
const take = 1;
const values = [];
function* squares() {
let current = 1;
while (current <= 5) {
yield current * current;
current = current + 1;
}
}
for (const value of squares()) {
if (values.length >= take) {
break;
}
values.push(value);
}
console.log("take=" + take);
console.log("values=" + values.join(","));
const take = 3;
const values = [];
function* squares() {
let current = 1;
while (current <= 5) {
yield current * current;
current = current + 1;
}
}
for (const value of squares()) {
if (values.length >= take) {
break;
}
values.push(value);
}
console.log("take=" + take);
console.log("values=" + values.join(","));
take ← 2, values ← (empty)
1const take→ 2 = 2; //@take=1, 32const values→ (empty) = [];current ← 1
1const take = 2; //@take=1, 32const values = [];34function* squares() {5 let current→ 1 = 1;6 while (current <= 5) {while (current <= 5)
pass 1 of 34function* squares() {5 let current = 1;6 while (current1 <= 5) {7 yield current * current1;8 current = current + 1;All 3 passes — pass 1 is the card above pass currentvalues.lengthtake1 1 — — 2 2 — — 3 3 2 2 values ← 1, current ← 1
5 let current = 1;6 while (current <= 5) {7 yield current→ 1 * current;8 current = current→ 2 + 1;9 }10}1112for (const value of squares()) {13 if (values.length >= take) {14 break;15 }16 values.push(value1);17}values this step(empty) → 1valuesvalues ← 1,4, current ← 2
5 let current = 1;6 while (current <= 5) {7 yield current→ 2 * current;8 current = current→ 3 + 1;9 }10}1112for (const value of squares()) {13 if (values.length >= take) {14 break;15 }16 values.push(value4);17}values this step1 → 1,4valuesif (values.length >= take)
12for (const value of squares()) {13 if (values.length2 >= take2) {14 break;15 }console.log("take=" + take);
16 values.push(value);17}1819console.log("take=" + take2);20console.log("values=" + values1,4.join(","));outputtake=2 values=1,4
take ← 1, values ← (empty)
1const take→ 1 = 1;2const values→ (empty) = [];current ← 1
1const take = 1;2const values = [];34function* squares() {5 let current→ 1 = 1;6 while (current <= 5) {while (current <= 5)
pass 1 of 24function* squares() {5 let current = 1;6 while (current1 <= 5) {7 yield current * current1;8 current = current + 1;values ← 1, current ← 1
5 let current = 1;6 while (current <= 5) {7 yield current→ 1 * current;8 current = current→ 2 + 1;9 }10}1112for (const value of squares()) {13 if (values.length >= take) {14 break;15 }16 values.push(value1);17}values this step(empty) → 1valueswhile (current <= 5)
pass 2 of 24function* squares() {5 let current = 1;6 while (current2 <= 5) {7 yield current * current2;8 current = current + 1;if (values.length >= take)
12for (const value of squares()) {13 if (values.length1 >= take1) {14 break;15 }console.log("take=" + take);
16 values.push(value);17}1819console.log("take=" + take1);20console.log("values=" + values1.join(","));outputtake=1 values=1
take ← 3, values ← (empty)
1const take→ 3 = 3;2const values→ (empty) = [];current ← 1
1const take = 3;2const values = [];34function* squares() {5 let current→ 1 = 1;6 while (current <= 5) {while (current <= 5)
pass 1 of 44function* squares() {5 let current = 1;6 while (current1 <= 5) {7 yield current * current1;8 current = current + 1;All 4 passes — pass 1 is the card above pass currentvalues.lengthtake1 1 — — 2 2 — — 3 3 — — 4 4 3 3 values ← 1, current ← 1
5 let current = 1;6 while (current <= 5) {7 yield current→ 1 * current;8 current = current→ 2 + 1;9 }10}1112for (const value of squares()) {13 if (values.length >= take) {14 break;15 }16 values.push(value1);17}values this step(empty) → 1valuesvalues ← 1,4, current ← 2
5 let current = 1;6 while (current <= 5) {7 yield current→ 2 * current;8 current = current→ 3 + 1;9 }10}1112for (const value of squares()) {13 if (values.length >= take) {14 break;15 }16 values.push(value4);17}values this step1 → 1,4valuesvalues ← 1,4,9, current ← 3
5 let current = 1;6 while (current <= 5) {7 yield current→ 3 * current;8 current = current→ 4 + 1;9 }10}1112for (const value of squares()) {13 if (values.length >= take) {14 break;15 }16 values.push(value9);17}values this step1,4 → 1,4,9valuesif (values.length >= take)
12for (const value of squares()) {13 if (values.length3 >= take3) {14 break;15 }console.log("take=" + take);
16 values.push(value);17}1819console.log("take=" + take3);20console.log("values=" + values1,4,9.join(","));outputtake=3 values=1,4,9