tags:

views:

63

answers:

3

What is happening here??

irb(main):001:0> a= nil
=> nil
irb(main):002:0> b = nil
=> nil
irb(main):003:0> a
=> nil
irb(main):004:0> a+b
NoMethodError: undefined method `+' for nil:NilClass
    from (irb):4
    from :0
irb(main):005:0> if a.nil? or b.nil?; a,b=0;end;
irb(main):006:0* c = a+b
TypeError: nil can't be coerced into Fixnum
    from (irb):6:in `+'
    from (irb):6
    from :0
irb(main):007:0>

How can you safely perform arithmetic by transforming nil to an number?

+3  A: 

Why would you want to add nil? It's specifically designed to be something that represents the lack of a value (note: nil is NOT 0).

If what you're actually wanting to do is set both values to 0 if either is currently nil, then what you actually want is this:

if a.nil? or b.nil?; a,b=0,0; end

Your mistake in the code above was the a,b=0 portion, which only sets the value of a to 0 - it sets b to nil because the left hand side is looking for two values, and only one is provided on the right (so the others are assumed to be nil).

Amber
+3  A: 

Depending on why there's a nil instead of a number, you could decide that it's good for you to consider nil as 0; in that case, you can do something like:

c = (a || 0) + (b || 0)

This, of course, only makes sense if you know why you have a nil instead of a number...

giorgian
I personally prefer `or` over `||`, it's just simpler for a lot of people to read (even though I've done enough programming that I wind up reading `||` as "or" anyways :P).
Amber
@Dav: what about the `@foo ||= ...` syntax? I use it a lot, so why not to always use `||`? Actually I'm just rationalizing: I simply prefer `||` over `or` :)
giorgian
`||` also has precedence over `or`, so the two are not always interchangeable.
Jimmy Cuadra
That precedence is actually why I like it, Jimmy - in my mind, `||` is better saved for actual logic operations most of the time; keeping `or` for actual "I want the actual second value sometimes" cases.
Amber
+2  A: 

Your parallel assignment (a, b = 0) results in a=0 and b=nil, i.e. it assigns 0 to a and nil to b, because there is only one value on the right hand side.

What you want is: if a.nil? or b.nil?; a = b = 0; end c = a + b

Obviously the code is still broken, since you overwrite any non-nil values of a and b with 0 when a or b is nil.

liwp