Company logo
  • Jobs
  • Bootcamp
  • About Us
  • For professionals
    • Home
    • Jobs
    • Courses
    • Questions
    • Teachers
    • Bootcamp
  • For business
    • Home
    • Our process
    • Plans
    • Assessments
    • Payroll
    • Blog
    • Calculator

0

92
Views
Restart a generator by delegating to itself in the end

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>

7 months ago · Juan Pablo Isaza
2 answers
Answer question

0

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>

7 months ago · Juan Pablo Isaza Report

0

  1. Another case of inifity loop / Stackoverflow:
        function* myGenerator() {
            // when nothing to yield temply
            yield* myGenerator();
        }
  1. 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:

enter image description here

7 months ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post job Plans Our process Sales
Legal
Terms and conditions Privacy policy
© 2023 PeakU Inc. All Rights Reserved.