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.
source to share
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()
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 :-)
source to share
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;
};
}
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 .
source to share
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
source to share