ECMAScript 6 introduces generators, iterators and syntax sugar for iteration. Node.JS v0.11.4 with the flags
--harmony --use_strict --harmony_generators
understands the following generator
function* fibonacci() {
let previous = 0;
let current = 1;
while(true) {
let temp = previous;
previous = current;
yield current = temp + current;
}
}
I can then print the Fibonacci numbers less than 1000.
for(let value of fibonacci()) {
if(value > 1000) { break; }
console.log(value);
}
For this example a while loop instead of a for loop would be more natural, similar to
while(value of fibonacci() < 1000) {
console.log(value);
}
Can iteration of iterators be done with a while loop instead of a for loop?
You can call a generator step by step using next function
var sequence = fibonacci();
var value;
while ((value = sequence.next()) < 1000) {
console.log(value);
}
plus, maybe even a nicer solution would be something like:
function* fibonacci(limit){
let previous = 0;
let current = 1;
while(previous + current < limit) {
let temp = previous;
previous = current;
yield current = temp + current;
}
}
for(let value of fibonacci(1000)) {
console.log(value);
}
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
function *bar(){
yield 1;
yield 2;
yield 3;
return 4;
}
var value,
g = bar();
while((value = g.next()).value){
console.log(value);
}
//Object {value: 1, done: false}
//Object {value: 2, done: false}
//Object {value: 3, done: false}
//Object {value: 4, done: true}
Yes, it is possible to do this by using the regular generator methods.
var fib = fibonacci(), value;
while( (value = fib.next()) < 1000 ) {
console.log(value);
}
Although I seem to prefer the for...of statement which takes care of handling those next calls and dealing with StopIteration(if the sequence is finite).
Related
I have a general question which is about whether it is possible to make zero-allocation iterators in Javascript. Note that by "iterator" I am not married to the current definition of iterator in ECMAScript, but just a general pattern for iterating over user-defined ranges.
To make the problem concrete, say I have a list like [5, 5, 5, 2, 2, 1, 1, 1, 1] and I want to group adjacent repetitions together, and process it into a form which is more like [5, 3], [2, 2], [1, 4]. I then want to access each of these pairs inside a loop, something like "for each pair in grouped(array), do something with pair". Furthermore, I want to reuse this grouping algorithm in many places, and crucially, in some really hot inner loops (think millions of loops per second).
Question: Is there an iteration pattern to accomplish this which has zero overhead, as if I hand-wrote the loop myself?
Here are the things I've tried so far. Let's suppose for concreteness that I am trying to compute the sum of all pairs. (To be clear I am not looking for alternative ways of writing this code, I am looking for an abstraction pattern: the code is just here to provide a concrete example.)
Inlining the grouping code by hand. This method performs the best, but obscures the intent of the computation. Furthermore, inlining by hand is error-prone and annoying.
function sumPairs(array) {
let sum = 0
for (let i = 0; i != array.length; ) {
let elem = array[i++], count = 1
while (i < array.length && array[i] == elem) { i++; count++; }
// Here we can actually use the pair (elem, count)
sum += elem + count
}
return sum
}
Using a visitor pattern. We can write a reduceGroups function which will call a given visitor(acc, elem, count) for each pair (elem, count), similar to the usual Array.reduce method. With that our computation becomes somewhat clearer to read.
function sumPairsVisitor(array) {
return reduceGroups(array, (sofar, elem, count) => sofar + elem + count, 0)
}
Unfortunately, Firefox in particular still allocates when running this function, unless the closure definition is manually moved outside the function. Furthermore, we lose the ability to use control structures like break unless we complicate the interface a lot.
Writing a custom iterator. We can make a custom "iterator" (not an ES6 iterator) which exposes elem and count properties, an empty property indicating that there are no more pairs remaining, and a next() method which updates elem and count to the next pair. The consuming code looks like this:
function sumPairsIterator(array) {
let sum = 0
for (let iter = new GroupIter(array); !iter.empty; iter.next())
sum += iter.elem + iter.count
return sum
}
I find this code the easiest to read, and it seems to me that it should be the fastest method of abstraction. (In the best possible case, scalar replacement could completely collapse the iterator definition into the function. In the second best case, it should be clear that the iterator does not escape the for loop, so it can be stack-allocated). Unfortunately, both Chrome and Firefox seem to allocate here.
Of the approaches above, the custom-defined iterator performs quite well in most cases, except when you really need to put the pedal to the metal in a hot inner loop, at which point the GC pressure becomes apparent.
I would also be ok with a Javascript post-processor (the Google Closure Compiler perhaps?) which is able to accomplish this.
Check this out. I've not tested its performance but it should be good.
(+) (mostly) compatible to ES6 iterators.
(-) sacrificed ...GroupingIterator.from(arr) in order to not create a (imo. garbage) value-object. That's the mostly in the point above.
afaik, the primary use case for this is a for..of loop anyways.
(+) no objects created (GC)
(+) object pooling for the iterators; (again GC)
(+) compatible with controll-structures like break
class GroupingIterator {
/* object pooling */
static from(array) {
const instance = GroupingIterator._pool || new GroupingIterator();
GroupingIterator._pool = instance._pool;
instance._pool = null;
instance.array = array;
instance.done = false;
return instance;
}
static _pool = null;
_pool = null;
/* state and value / payload */
array = null;
element = null;
index = 0;
count = 0;
/* IteratorResult interface */
value = this;
done = true;
/* Iterator interface */
next() {
const array = this.array;
let index = this.index += this.count;
if (!array || index >= array.length) {
return this.return();
}
const element = this.element = array[index];
while (++index < array.length) {
if (array[index] !== element) break;
}
this.count = index - this.index;
return this;
}
return() {
this.done = true;
// cleanup
this.element = this.array = null;
this.count = this.index = 0;
// return iterator to pool
this._pool = GroupingIterator._pool;
return GroupingIterator._pool = this;
}
/* Iterable interface */
[Symbol.iterator]() {
return this;
}
}
var arr = [5, 5, 5, 2, 2, 1, 1, 1, 1];
for (const item of GroupingIterator.from(arr)) {
console.log("element", item.element, "index", item.index, "count", item.count);
}
I am new to javascript and can't understand such a behaviour of generator function. Why does it output only odd nums(1,3,5,7,9)?
function* numberGen(n){
for (let i=0;i<n;i++){
yield i
}
}
const num = numberGen(10)
while (num.next().value!=undefined){
console.log(num.next().value)
}
You're calling num.next() twice in every iteration. You're calling it once in the while() header to check whether the result is undefined, then you're calling it a second time in the body to log the value. Each call retrieves the next item from the generator. So you check the even items for null, and log the odd item after it.
Instead you should assign a variable to a single call
function* numberGen(n){
for (let i=0;i<n;i++){
yield i
}
}
const num = numberGen(10)
let i;
while ((i = num.next().value) !== undefined){
console.log(i)
}
Instead of calling the .next() method explicitly, you can use the built-in for-of iteration method.
function* numberGen(n) {
for (let i = 0; i < n; i++) {
yield i
}
}
const num = numberGen(10)
for (let i of num) {
console.log(i);
}
You call .next() twice per iteration, hence you skip every other number.
inside the while condition checking statement you consume one in two value just for checking, iterators are consumable, and that why we just see odd numbers, even number were used for truthy checks
function* numberGen(n){
for (let i=0;i<n;i++){
yield i
}
}
const num = numberGen(10);
//using spread opertaor to iterate all values
console.log([...num]);
//or you can use forOf
//for( number of num ){
// console.log(number);
//}
I have a function that computes product of numbers in an array. The function should work like this
function prod (array){
//compute and return product
}
var arr = [1,2,3,0,4,5,0,6,7,8,0,9];
the function call:
prod(arr); //should return 6
prod(arr); //should return 20
prod(arr); //should return 336 (6*7*8)
prod(arr); //should return 9
prod(arr); //should return 0
prod(arr); //should return 0
prod(arr); //should return 0
In scheme, this is done with continuations, by storing previous state of the function (state of the function is captured just before its exit point) see this
So, in short, I want the javascript function return different values at different times with same parameter passed everytime.
JavaScript is a well designed language, so I hope there must be something which can emulate this. If there happens to be nothing in JS to do it, I do not mind to conclude with failure and move on. So, feel free to say its impossible.
Thanks.
JavaScript is not capable of supporting continuations: it lacks tail-calls.
Generally I would write this to use a "queue" of sorts, although CPS is also do-able (just have a finite stack :-) Note that other state can also be captured in the closure, making it an "explicit continuation" of sorts ... in a very gross sense.
Example using a closure and a queue:
function prodFactory (array){
// dupe array first if needed, is mutated below.
// function parameters are always locally scoped.
array.unshift(undefined) // so array.shift can be at start
// also, perhaps more closured state
var otherState
// just return the real function, yippee!
return function prod () {
array.shift()
// do stuff ... e.g. loop array.shift() and multiply
// set otherState ... eat an apple or a cookie
return stuff
}
}
var prod = prodFactory([1,2,3,0,4,5,0,6,7,8,0,9])
// array at "do stuff", at least until "do stuff" does more stuff
prod() // [1,2,3,0,4,5,0,6,7,8,0,9]
prod() // [2,3,0,4,5,0,6,7,8,0,9]
prod() // [3,0,4,5,0,6,7,8,0,9]
Happy coding.
"Finished implementation". Although this particular problem can avoid array mutation and just use an index: the same concepts apply. (Well, slightly different. With just an index the closed over variable would be altered, whereas with this approach an object is mutated.)
function prodFactory (array) {
array = array.slice(0)
return function prod () {
var p = 1
for (var n = array.shift(); n; n = array.shift()) {
p *= n
}
return p
}
}
var prod = prodFactory([1,2,3,0,4,5,0,6,7,8,0,9])
prod() // 6
prod() // 20
prod() // 336
You can give the function a property that will be remembered between calls:
function prod (array){
if (typeof prod.index === "undefined" || prod.currentArray != array) {
prod.currentArray = array;
prod.index = 0;
}
if (prod.index >= array.length)
return 0;
//compute and return product
var p = 1,
c;
while (prod.index < array.length) {
c = array[prod.index++];
if (c === 0)
return p;
p *= c;
}
return p;
}
I'm just guessing from your description of what should be returned that on an individual call to the function it should take the product of all of the numbers up to but not including the next zero or the end of the array. Calls after the end of the array should return 0? I may have the algorithm wrong for that, but you get the idea for what I'm suggesting to remember the function state between calls.
I've added a property to remember the current array being processed. As long as you keep passing the same array in to the function it will continue with the next elements, but if you pass a different array it will reset...
you can try something like
var index = 0;
function prod (array){
if(index < array.length){
var prod=1;
for(int i=index;i<array.length;i++){
if(array[i] != 0){
prod = prod * array[i];
}
else{
index = i+1;
return prod;
}
}
}
return 0;
}
this will update the global variable index everytime the function is called.
What you're looking for here are generators. As of 1.7, JavaScript supports them.
A lot of people where confused by my last question. I hope I can clear things up with this one. HERE is what I need to do:
var arr = ["Init Value", "Does Not", "Matter"];
arr.onGet = updater; // Register arr with updater function
alert(arr[0]); // should return 1;
alert(arr[0]); // should return 2;
alert(arr[0]); // should return 3;
alert(arr[0]); // should return 4;
alert(arr[0]); // should return 5;
var counter = 0;
function updater(){
counter = counter + 1;
return counter;
}
See what I did there? Init value does not matter, it's the updater function that is pulling the values.
Now this does not work of course, since arr does not automatically call the function updater and there is no event onGet. Some people might say, well that's just crazy talk, how can you run a function when it's not even called. That is true, but a VARIABLE is called (in our case arr[0], so can't you just bind(link) it up to another function when arr[0] is called? In essence, this is an auto-updater, hence my question.
Also, I have given up trying to work this in IE7, how about just Google Chrome?
Solution by Skyd:
function onGet(obj) {
var index = 0;
var counter = 0;
for (var prop in obj) {
(function(thisIndex, thisProp) {
obj.__defineGetter__(thisIndex, function() {
counter = counter + 1;
return counter ;
});
})(index, prop)
index++;
};
obj.__defineGetter__("length", function() {
return 1000;
});
return obj;
}
var myObj = [100,200,300];
onGet(myObj);
alert(myObj[1]); // 1
alert(myObj[2]); // 2
alert(myObj[3]); // 3
alert(myObj.length); // 1000 <-- Arbitary value which you can change
You should look into javascript Setters and Getters, which lets you run functions when a certain property is being accessed or modified. It works great on objects. For arrays, its a little harder, since arrays can potentially have infinite properties (where properties are its indicies). If you have a fixed size array though, then something like this might work:
var arr = ["Fixed", "Array", "Size", "Will", "Not", "Ever", "Change"];
for (var i=0; i<arr.length; i++){
debug(i);
(function(index){
arr.__defineGetter__(index, function(){return updater();});
})(i);
}
alert(arr[0]) // will return results of updater() call;
It may be better to use a custom object with a getter/setter rather than using a fixed size array.
Also, look at these links: Getter/setter on javascript array? and http://javascriptweblog.wordpress.com/2010/11/15/extending-objects-with-javascript-getters/
I wrote a simple map implementation for some task. Then, out of curiosity, I wrote two more. I like map1 but the code is kinda hard to read. If somebody is interested, I'd appreciate a simple code review.
Which one is better? Do you know some other way to implement this in javascript?
var map = function(arr, func) {
var newarr = [];
for (var i = 0; i < arr.length; i++) {
newarr[i] = func(arr[i]);
}
return newarr;
};
var map1 = function(arr, func) {
if (arr.length === 0) return [];
return [func(arr[0])].concat(funcmap(arr.slice(1), func));
};
var map2 = function(arr, func) {
var iter = function(result, i) {
if (i === arr.length) return result;
result.push(func(arr[i]));
return iter(result, i+1);
};
return iter([], 0);
};
Thanks!
EDIT
I am thinking about such function in general.
For example, right now I am going to use it to iterate like this:
map(['class1', 'class2', 'class3'], function(cls) {
el.removeClass(cls);
});
or
ids = map(elements, extract_id);
/* elements is a collection of html elements,
extract_id is a func that extracts id from innerHTML */
What about the map implementation used natively on Firefox and SpiderMonkey, I think it's very straight forward:
if (!Array.prototype.map) {
Array.prototype.map = function(fun /*, thisp*/) {
var len = this.length >>> 0; // make sure length is a positive number
if (typeof fun != "function") // make sure the first argument is a function
throw new TypeError();
var res = new Array(len); // initialize the resulting array
var thisp = arguments[1]; // an optional 'context' argument
for (var i = 0; i < len; i++) {
if (i in this)
res[i] = fun.call(thisp, this[i], i, this); // fill the resulting array
}
return res;
};
}
If you don't want to extend the Array.prototype, declare it as a normal function expression.
As a reference, map is implemented as following in jQuery
map: function( elems, callback ) {
var ret = [];
// Go through the array, translating each of the items to their
// new value (or values).
for ( var i = 0, length = elems.length; i < length; i++ ) {
var value = callback( elems[ i ], i );
if ( value != null )
ret[ ret.length ] = value;
}
return ret.concat.apply( [], ret );
}
which seems most similar to your first implementation. I'd say the first one is preferred as it is the simplest to read and understand. But if performance is your concern, profile them.
I think that depends on what you want map to do when func might change the array. I would tend to err on the side of simplicity and sample length once.
You can always specify the output size as in
var map = function(arr, func) {
var n = arr.length & 0x7fffffff; // Make sure n is a non-neg integer
var newarr = new Array(n); // Preallocate array size
var USELESS = {};
for (var i = 0; i < n; ++i) {
newarr[i] = func.call(USELESS, arr[i]);
}
return newarr;
};
I used the func.call() form instead of just func(...) instead since I dislike calling user supplied code without specifying what 'this' is, but YMMV.
This first one is most appropriate. Recursing one level for every array item may make sense in a functional language, but in a procedural language without tail-call optimisation it's insane.
However, there is already a map function on Array: it is defined by ECMA-262 Fifth Edition and, as a built-in function, is going to be the optimal choice. Use that:
alert([1,2,3].map(function(n) { return n+3; })); // 4,5,6
The only problem is that Fifth Edition isn't supported by all current browsers: in particular, the Array extensions are not present in IE. But you can fix that with a little remedial work on the Array prototype:
if (!Array.prototype.map) {
Array.prototype.map= function(fn, that) {
var result= new Array(this.length);
for (var i= 0; i<this.length; i++)
if (i in this)
result[i]= fn.call(that, this[i], i, this);
return result;
};
}
This version, as per the ECMA standard, allows an optional object to be passed in to bind to this in the function call, and skips over any missing values (it's legal in JavaScript to have a list of length 3 where there is no second item).
There's something wrong in second method. 'funcmap' shouldn't be changed to 'map1'?
If so - this method loses, as concat() method is expensive - creates new array from given ones, so has to allocate extra memory and execute in O(array1.length + array2.length).
I like your first implementation best - it's definitely easiest to understand and seems quick in execution to me. No extra declaration (like in third way), extra function calls - just one for loop and array.length assignments.
I'd say the first one wins on simplicity (and immediate understandability); performance will be highly dependent on what the engine at hand optimizes, so you'd have to profile in the engines you want to support.