WesR
WesR

Reputation: 1512

underscore.js reduce error? different behavior than Ruby?

It appears that the reduce method of underscore.js assumes that the 'memo' value is a scalar, whereas Ruby will accept a general object. Would this be a bug, a limitation of underscore.js or am I somehow screwing up?

Here is a trivial example of reduce in Ruby 1.9.3.

irb(main):020:0> a = [1, 1, 2, 2]
=> [1, 1, 2, 2]
irb(main):021:0> a.reduce([]) {|accum, nxt| accum.push(nxt)}
=> [1, 1, 2, 2]

Here is what I believe to be the equivalent code using _.js

var _ =Underscore.load();
function tryReduce() {
 var a = [1, 1, 2, 2]
 var b = _.reduce(a, function(out, nxt) {
   return out.push(nxt);
 }, [])
 Logger.log(b)
}

In Google Script the code bombs with

TypeError: Cannot find function push in object 1. (line 6, file "tryingStuff")

However this code runs and gives the correct result, 1006.

var _ =Underscore.load();
function tryReduce() {
 var a = [1, 1, 2, 2]
 var b = _.reduce(a, function(out, nxt) {
   return out + nxt;
 }, 1000)
 Logger.log(b)
}

Upvotes: 0

Views: 158

Answers (1)

Jonathan Lonowski
Jonathan Lonowski

Reputation: 123463

The issue is that Array#push returns different values in each language. While Ruby's returns the Array itself, JavaScript's returns the updated length.

_.reduce() can work with Array memos, but you have to ensure that the Array is what's returned in the iterator:

var b = _.reduce(a, function(out, nxt) {
   out.push(nxt);
   return out;
}, [])

Otherwise, the 1st round ends with a Number (the length) and the next round throws an error since Number#push doesn't exist. This is the "scalar" you mentioned:

It appears that the reduce method of underscore.js assumes that the 'memo' value is a scalar

Upvotes: 2

Related Questions