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>
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>
function* myGenerator() {
// when nothing to yield temply
yield* myGenerator();
}
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: