I am wondering about the drawbacks of restarting a generator by delegating to itself in the end.
function* myGenerator(){
yield "value1";
yield "value2";
yield "value3";
yield "value4";
yield* myGenerator();
}
const generate = myGenerator();
for (let i = 0; i<15; i ){
document.getElementById("output").innerHTML = generate.next().value "[" i "]" "<br />";
}
<div id="output"></div>
One drawback that came up to my mind is the possibility of an infinite loop if it is used as an iterator. It can be bypassed with a counter, though.
function* myGenerator(c){
let counter = c? c: 0;
yield "value1";
yield "value2";
yield "value3";
yield "value4";
counter ;
if (counter < 3){
yield* myGenerator(counter);
}
}
const generate = myGenerator();
for (let val of generate){
document.getElementById("output").innerHTML = val "<br />";
}
<div id="output"></div>
CodePudding user response:
The recursive calls will consume the call stack, and at every yield this stack must be saved and restored.
Your example is a case of tail recursion, so it is easy to rewrite as a loop:
function* myGenerator() {
while (true) {
yield "value1";
yield "value2";
yield "value3";
yield "value4";
}
}
const generate = myGenerator();
for (let i = 0; i < 15; i ) {
document.getElementById("output").innerHTML = generate.next().value "[" i "]<br>";
}
<div id="output"></div>
As to avoiding that you try to consume an infinite series, you could use a generic function for that.
Unrelated, but I'd only assign once to innerHTML
:
function* myGenerator() {
while (true) {
yield "value1";
yield "value2";
yield "value3";
yield "value4";
}
}
function* islice(iterator, count) {
for (let value of iterator) {
if (--count < 0) return;
yield value;
}
}
const generate = islice(myGenerator(), 15);
const values = Array.from(generate, (value, i) => value "[" i "]");
document.getElementById("output").innerHTML = values.join("<br>");
<div id="output"></div>
CodePudding user response:
- Another case of inifity loop / Stackoverflow:
function* myGenerator() {
// when nothing to yield temply
yield* myGenerator();
}
- Bad for GC, too many instance created.
var cur_counter = 0;
function* myGenerator() {
cur_counter ;
console.log("current count of generator: " cur_counter);
yield 1;
yield* myGenerator();
cur_counter--; // will never be called
}
EDIT
Callstack: