Javascript function generator

I need to create a function generator that iterates over an infinite sequence, like a fibonacci sequence. It should return the next value in sequence when called. I am provided with a function prototype:

function genfib() {
  return function fib() {
  }
}

      

it should be used like this:

var fib = genfib();
fib(); // -> returns 0
fib(); // -> returns 1
fib(); // -> returns 1
fib(); // -> returns 2

      

I am confused about what gets executed every time I call fib()

. I tried to do something like

function genfib() {
  var count = 1;
  if (count === 1) {
    count++;
    yield 0;
  }
  else if (count === 2) {
    count++;
    yield 1;
  }
  var a = 0;
  var b = 1;
  return function fib() {
    while(1) {
      count = a + b;
      a = b;
      b = count;
      yield count;
    }
  }
}

      

But it doesn't work. I don't know how to set it up to run if/else

for the first two numbers in the sequence fib

and then run the loop while

once for each subsequent call.

+3


source to share


4 answers


If you ask me, there is yield

no place for this function, just some clever use of JavaScript closure .

You had the right idea in the beginning - you need a function that returns a function. Outside of the inner function, there are a couple of variables - one for the old one, one for the next. Inside the function, all you have to do is compute a new value next

and then set old

to the previous value next

. To toggle their values, you need a placeholder variable.



function genfib() {
  var next = 1
  var old = 0
  return function fib() {
    var newNext= next + old
    old = next
    next = newNext
    return next
  }
}

var fib = genfib()

var result = []

for ( var i = 0; i < 10; i++ )
  result.push( fib() )

document.body.innerHTML = result.join()
      

Run codeHide result


Of course this does not account for the first function call, which is a special case (1 must be returned twice.) But I'll leave that to you to figure out :-)

+2


source


If you want to use ES6 generators and yield

then here's the approach:

function *fibonacci() {
    var [prev, current] = [0, 1];

    while (true) {
        [prev, current] = [current, current+prev];
        yield current;
    }
}

      

One way to iterate over the results is with a loop for-of

:

for (var v of fibonacci()) {
    console.log(v);
    if (v > 100) break;
}

      



Note that destructuring assignment is var [prev, current] =

supported in FF and Traceur, but not in Chrome or node at this time. Rewrite it as:

function *fibonacci() {
    var prev = 0, current = 1, oldprev;

    while (true) {
        oldprev = prev;
        prev = current;
        yield current += oldprev;
    }
}

      

If you want to get the semantics of a function prototype, then:

function genfib() {
    var iterator = fibonacci();
    return function fib() {
        return iterator.next().value;
    };
}

      

+7


source


function* fib(num) {
  var a = num, b = a + 1, c = a;

  while (true) {
    yield a;
    c = a;
    a = b;
    b = c + b;
  }
}

var it = fib(0);
console.log(it.next().value); // 0
console.log(it.next().value); // 1
console.log(it.next().value); // 1
console.log(it.next().value); // 2
console.log(it.next().value); // 3
console.log(it.next().value); // 5
console.log(it.next().value); // 8
console.log(it.next().value); // 13

      

For a high-level overview on how to use generators, check out this post .

+1


source


function* fibonacci(){
  var fn1 = 1;
  var fn2 = 1;
  while (true){  
    var current = fn2;
    fn2 = fn1;
    fn1 = fn1 + current;
    var reset = yield current;
    if (reset){
        fn1 = 1;
        fn2 = 1;
    }
  }
}

var sequence = fibonacci();
console.log(sequence.next().value);     // 1
console.log(sequence.next().value);     // 1
console.log(sequence.next().value);     // 2
console.log(sequence.next().value);     // 3
console.log(sequence.next().value);     // 5
console.log(sequence.next().value);     // 8
console.log(sequence.next().value);     // 13
console.log(sequence.next(true).value); // 1
console.log(sequence.next().value);     // 1
console.log(sequence.next().value);     // 2
console.log(sequence.next().value);     // 3

      

0


source







All Articles