Why can I here sum numbers

<meta http-equiv="content-type" content="text/html; 

charset=ISO-8859-1">

Hello,

I have a method that takes a unlimited number of integers and adds them all together .

So I did this :

def sum (*numbers)
   numbers.each do |n|
      sum += n if n.is_a? Integer
   end
end

but when I run it I see this error message :

block in sum': undefined method+’ for nil:NilClass (NoMethodError)
from each' fromsum’
from `




why do I get a nilClass there. As far as I know this is a normal
way to add things up.



Roelof







The ‘sum’ variable needs to be initialized or else it takes the value of
nil. So in the line ‘sum += n’, sum is nil. You can solve this by
setting
sum = 0 at the beginning of the method.

Yup, you need sum to be defined. Use inject to do just that

On Thu, Nov 20, 2014 at 9:31 AM, Jeremy Axelrod
[email protected]
wrote:

block in sum': undefined method+’ for nil:NilClass (NoMethodError)

Augusts B.

Creative MobileKronvalda bulvaris 10, Riga**office: 00371 67227747
mobile: 00371 29957771
www.creo.mobi http://www.creo.mobi/

Thanks,

That is solved,
But now I have this test :

Test.assert_equals(6, sum (1,2,3) )

And I see this error :

-e:10: syntax error, unexpected ( arg, expecting keyword_do or '{' or '(' Test.assert_equals(6, sum (1,2,3) )

Roelof

Jeremy Axelrod schreef op 20-11-2014 8:31:
The 'sum' variable needs to be initialized or else it takes the value of nil. So in the line 'sum += n', sum is nil. You can solve this by setting sum = 0 at the beginning of the method.

On Wed, Nov 19, 2014 at 11:22 PM, Roelof W. <[email protected]> wrote:
Hello,

I have a method that takes a unlimited number of integers and adds them all together .

So I did this :

def sum 
(*numbers)
   numbers.each do |n|
      sum += n if n.is_a? Integer
   end
end

but when I run it I see this error message :

block in sum': undefined method+’ for nil:NilClass (NoMethodError)
from each' fromsum’
from `




why do I get a nilClass there. As far as I know this is a
normal way to add things up.



Roelof













What if you put a number in the array?

Sent from my phone

Accidental submit…

As I started… use Inject

def sum (*numbers)
numbers.inject {|sum, n| sum + n }
end

Inject initialises an empty (zero) receptacle for aggregated data for
you.

More at http://blog.jayfields.com/2008/03/ruby-inject.html

On Thu, Nov 20, 2014 at 9:38 AM, Roelof W. [email protected] wrote:

Test.assert_equals(6, sum (1,2,3) )

end
why do I get a nilClass there. As far as I know this is a normal way to
add things up.

Roelof

Augusts B.

Creative MobileKronvalda bulvaris 10, Riga**office: 00371 67227747
mobile: 00371 29957771
www.creo.mobi http://www.creo.mobi/

On Thu, Nov 20, 2014 at 9:23 AM, Jeremy Axelrod
[email protected] wrote:

What if you put a number in the array?

In the method you cannot know whether there are numbers in the
Enumerable passed to the method.

Kind regards

robert

On Thu, Nov 20, 2014 at 8:41 AM, Augusts B. [email protected]
wrote:

As I started… use Inject

def sum (*numbers)
numbers.inject {|sum, n| sum + n }
end

Inject initialises an empty (zero) receptacle for aggregated data for you.

No. Your approach is broken because

irb(main):001:0> [].inject {|sum, n| sum + n }
=> nil

More at http://blog.jayfields.com/2008/03/ruby-inject.html

That has it correct in the first example. You need to pass in the
neutral element of the operation:

irb(main):002:0> [].inject(0) {|sum, n| sum + n }
=> 0

Cheers

robert

Robert K. schreef op 20-11-2014 9:28:

Can I have a answer to my question why the test is failing ??

Roelof

May be the space between sum and (1,2,3) is throwing error.
Try this
Test.assert_equals(6, sum(1,2,3) )

I would recommend the “inject” approach here. The reason why you are
getting nilClass and the error “undefined method `+’ for nil:NilClass”
is
because in the block, you are trying to call the “+” method on the “sum”
object which is essentially nil. A way to avoid this error is by
defining a
variable “sum” outside the block and setting it to 0.

On Thu, Nov 20, 2014 at 1:01 PM, Jeremy Axelrod
[email protected]

What is the result of “puts sum(1, 2, 3).inspect”?

If the result is “[1, 2, 3]”, then you should return sum variable at
the end of sum method like below, but I recommend to use inject method.

def sum (*numbers)

sum = 0

numbers.each do |n|

sum += n if n.is_a? Integer

end

sum

end

2014년 11월 20일 목요일, Roelof W.[email protected]님이 작성한 메시지:

How about this?

def sum(*num)

num.sum{|a| a.is_a?(*Integer*) ? a : *0*}

end

On Thu, Nov 20, 2014 at 5:21 PM, Robert K.
[email protected]

On Thu, Nov 20, 2014 at 9:46 AM, 홍철주 [email protected] wrote:

What is the result of “puts sum(1, 2, 3).inspect”?

What is the sound of one hand clapping. Sorry, your sentence just
triggered an association with me. :slight_smile:

If the result is “[1, 2, 3]”, then you should return sum variable at the end
of sum method like below, but I recommend to use inject method.

def sum (*numbers)
sum = 0
numbers.each do |n|
sum += n if n.is_a? Integer
end
sum
end

I would omit the test because coercing takes care of type conversions.
If at all, I’d use #to_int but not the type test.
See
http://blog.rubybestpractices.com/posts/rklemme/019-Complete_Numeric_Class.html

So that would still give

def sum(*numbers)
inject(0) {|s,x| s+x}
end

or

def sum(*numbers)
inject(0) {|s,x| s+x.to_int}
end

Roelof, the space before (1,2,3) is the issue.

Kind regards

robert

Robert K. schreef op 20-11-2014 10:21:
inject(0) {|s,x| 
s+x}

Thanks,

I tried the inject way?? like this :

def sum (*numbers)
???? sum.inject(0) {|sum,nummer| sum + nummer}
end

with this test :

Test.assert_equals(6, sum(1,2,3) )

and now I see this error : -e:3: stack level too deep (SystemStackError)

Roelof

naming is important
you have a function ‘sum’ with a variable ‘sum’
the interpreter is calling the function where you expect it to use the
variable

On Thu, Nov 20, 2014 at 3:26 PM, Chris H. [email protected]
wrote:

naming is important
you have a function ‘sum’ with a variable ‘sum’
the interpreter is calling the function where you expect it to use the
variable

He is simply invoking #inject on the wrong object (i.e. result of
recursively invoking sum).

Cheers

robert

Since we’re playing:

def sum(*args)
args.inject {|a,b| a+b } or 0
end

Also works on strings.

Robert K. schreef op 20-11-2014 15:59:

robert

Thanks,

I had to do numbers.inject

One other problem.
The method schould reject everything which is not a integer.
numbers.inject gives a error if you do sum (1,“a”, 2)

Roelof

On Thu, Nov 20, 2014 at 4:09 PM, Roelof W. [email protected] wrote:

I had to do numbers.inject

Exactly.

One other problem.
The method schould reject everything which is not a integer.
numbers.inject gives a error if you do sum (1,“a”, 2)

Well, then it does reject non numbers. Generally I probably would
not add a test to that method that simply skips non numbers. Let each
method do one thing properly. If you need filtering you can always do
the filtering before the call.

sum(*numbers.grep(Integer))

Btw, I would declare the interface of the method like this:

def sum(numbers)

i.e. use a single Enumerable. I think that is more flexible because
you can pass in an Enumerator which can be used to delegate the
filtering to the iteration (and not have to do it upfront and convert
to an Array like is needed with *numbers):

irb(main):004:0> def sum(n) n.inject(0){|s,x|s+x} end
=> nil
irb(main):005:0> sum([1,2,“foo”].to_enum(:grep, Integer))
=> 3

Kind regards

robert