There are two possible ways I'd go on about this, given other languages that support this behavior:
1) One using Harmony proxies, which would let you doing meta-tables (kind of like in lua) and allow for lazy iterables. This would provide fhe following notation:
var arr = ...; // create the resource
for(var i=0;arr[i]<1000;i++){
arr[i]; // consume fibonacci numbers
}
2) The second using a take function letting you consume an iterable with .forEach like in C# or python. Which would allow the following notation:
takeWhile(fibGenerator,(item) => item<1000).forEach(... // consume with predicate
First approach - using harmony proxies
Note... for of loops through objects. It does not guarantee order at all. You can however do something like the following to get the notion of a lazy iterate.
You have to run node both with the --harmony_generators and --harmony_proxies flags:
var arr = ...; // create an array and proxy it, use a generator internally
arr[50]; // will calculate the 50th fibonacci element and return it.
arr[100];// will calculate the 100th fibonacci element and return it.
for(var i=0;arr[i]<1000;i++){
arr[i];//the i-th fibonacci number
}
It will only calculate numbers not fetched yet, this will allow you to use a simple for loop.
Here is how*:
var cache = [];
var handler = {
get: (function(){
function fibIterator(){
var t=0,a=0,b=0;
return function(){
t=a;
a+=b;
b=t;
return a;
}
}
var iterator = fibIterator();
return function (target, fibNumber) {
if (name in cache) {
return cache[name];
}
while(iterator < fibNumber){
// update indexes.
}
})()
}
};
var arr = Proxy.create(handler);
(Just don't expect it to be very fast)
*(using old proxy notation, since the new one isn't supported in node yet, will update once it gets support)
Side note, in JavaScript since functions can have internal state through closures, you don't even really need a generator
Second approach, using an iterator Take function.
This is what you'd normally do in languages like C# for this use case.
function takeWhile(generating, predicate){
var res = [],last;
do{
res.push(last=generating())
}while(predicate(last));
return res;
}
Then do something like
var res = takeWhile(fibIterator,function(item){
return item<1000;
});
res.forEach(function(){ ...
Or by count:
function take(generating,numToTake){
var res = [],num;
do{
res.push(last=generating())
}while(num++ < numToTake);
return res;
}
var res = take(fibIterator,1000);//first 1000 numbers