3

Why does [].sum gives an undefined method error?

[5, 15, 10].sum 
# => NoMethodError: undefined method `sum' for [5, 15, 10]:Array 

Doing ri Array#sum returns:

Array#sum

(from gem activesupport-4.2.6) Implementation from Enumerable
------------------------------------------------------------------------------
sum(identity = 0, &block)

------------------------------------------------------------------------------

Calculates a sum from the elements.

payments.sum { |p| p.price * p.tax_rate } payments.sum(&:price)

The latter is a shortcut for:

payments.inject(0) { |sum, p| sum + p.price }

It can also calculate the sum without the use of a block.

[5, 15, 10].sum # => 30                         ## <-- What?! >:(  
['foo', 'bar'].sum # => "foobar"
[[1, 2], [3, 1, 5]].sum => [1, 2, 3, 1, 5]

The default sum of an empty list is zero. You can override this default:

[].sum(Payment.new(0)) { |i| i.amount } # => Payment.new(0)

What's going on? What am I failing to understand? Or is my installation broken?

3
  • 2
    sum isn't predefined for either Arrays or Enumerables. It may be added by a library/framework such as ActiveSupport. Otherwise, you can use inject to calculate a sum. Commented Jun 5, 2016 at 23:23
  • I see. I misread the docs (or just didn't read them carefully enough.) For what it's worth, I'm aware of using inject() like that, but thanks for the suggestion. Map/reduce games are something I particularly like. :) Commented Jun 5, 2016 at 23:37
  • Many things from Rails are making their way over into core Ruby over time, so this line is pretty blurry. Still, watch out for the "ActiveSuport" hint in the docs. Commented Jun 6, 2016 at 4:52

2 Answers 2

6

It mentions (from gem activesupport-4.2.6) Implementation from Enumerable.

require 'active_support'
require 'active_support/core_ext'

2.2.2 > [5, 15, 10].sum
=> 30
Sign up to request clarification or add additional context in comments.

10 Comments

Ah. So it does. I guess I didn't understand the significance of that bit.
So the problem was that I didn't understand the docs. Thanks again. But I'd like to understand this better. It seems to me that sum() should be there as natively as max() is. What's the rationalization? More technically, how is this implemented? Are there different Enumerable modules? Or.. it's a guess, but I suppose that active_support adds that method (and perhaps others) to Enumerable. Maybe I can look, if I can find the source. Can anyone suggest some further reading? Is there a programmatic way to examine these things? Like, "Show me the inheritance chain of this method."
[].method(:sum).source_location will point to the file used
Nice! That's going to be useful. :)
The rationale behind it I'm not exactly sure, you could always write [5, 15, 10].reduce(:+) instead. It might be a good idea to look at the source code for Active Support Enumerable. Active Support adds a lot of useful extensions in general to Ruby, however beware that some things might seem like complete black magic such as Time.now + 5.send('days') (and you have to dig through a lot of source to find out how it's done).
|
2

Its already stated above in most answers that sum is not an instance method of array.

You can see all methods available on an object using object.methods. example [1,2,3].methods. Also you can refer to http://apidock.com/ruby/Array

[1,2,3].inject(0) {|sum,x| sum + x }

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.