Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why Underscore.js chain() method is not lazy?

According to Underscore.JS sources (https://github.com/jashkenas/underscore/blob/master/underscore.js):

// Start chaining a wrapped Underscore object.
chain: function() {
  this._chain = true;
  return this;
},

// Extracts the result from a wrapped and chained object.
value: function() {
  return this._wrapped;
}

chain() and value() functions are just simple wrappers for Underscore object.

So if I'm using following construction:

_.chain(someCollection)
.map(function1)   
.map(function2)
.map(function3)
.value()

Underscore will create two intermediate collections and will perform three enumerations.

Why the chain() and value() methods are not implemented as lazy evaluated like LINQ implements its methods? For example, this chain could be treated as:

_.chain(someCollection)
.map(function(x){
    return function3(function2(function1(x)));
})
.value();

Is there any JS related issues for this kind of implementation?

like image 462
Sane Avatar asked Jul 17 '13 11:07

Sane


1 Answers

Basically to make .chain() lazy the way you describe, it would require having almost two versions of each method. You would need the immediate response methods that do what the documentation says (returns an array) and you would need the lazy methods that do lazy evaluation (returns a function expecting to be run later for each element).

One way to implement this would be to write all of underscore as lazy and expose this as the chained underscore. Then expose normal underscore as a wrapper of lazy underscore that calls lazy underscore, immediately evaluates, and then returns the results. There's two main problems: (1) it's a lot more work and (2) it's a completely opposite architecture requiring all of underscore to be written as lazy just to support lazy evaluation of the chain method.

It's certainly doable, as exhibited by JSLinq and .NET's LINQ, but there's a huge cost in terms of developer time for development and maintenance, as well as increased complexity and likelihood of bugs. Underscore provides non-lazy evaluation of 80 different utility methods in 1,200 lines of code. JSLinq provides lazy-evaluation of 21 different utility methods in 7,000 lines of code. A lot more code, lower quantity of functions.

There's a trade off. Each developer gets to make their own decisions (as long as they're working for themselves).

like image 191
Samuel Neff Avatar answered Sep 30 '22 15:09

Samuel Neff