views:

60

answers:

2

I'm starting with Ruby, and while making some test samples, I've stumbled against an error in the code that I don't understand why it happens.

The code pretends to tests if a variable finn is defined?() and if it is defined, then it increments it. If it isn't defined, then it will define it with value 0 (zero). As the code threw an error, I started to decompose it in small pieces and run it, to better trace where the error was comming from. The code was run in IRB irb 0.9.5(05/04/13), using ruby 1.9.1p378

First I certify that the variable finn is not yet defined, and all is ok:

?> finn
NameError: undefined local variable or method `finn' for main:Object
        from (irb):134
        from /home/paulo/.rvm/rubies/ruby-1.9.1-p378/bin/irb:15:in `<main>'
>>

Then I certify that the following inline-condition executes as expected, and all is ok:

?> ((defined?(finn)) ? (finn+1):(0))
=> 0

And now comes the code that throws the error:

?> finn=((defined?(finn)) ? (finn+1):(0))
NoMethodError: undefined method `+' for nil:NilClass
        from (irb):143
        from /home/paulo/.rvm/rubies/ruby-1.9.1-p378/bin/irb:15:in `<main>'

I was expecting that the code would not throw any error, and that after executing the variable finn would be defined with a first value of 0 (zero). But instead, the code thows the error, and finn get defined but with a value of nil.

>> finn
=> nil

Where might the error come from?!? Why does the inline-condition work alone, but not when used for the finn assignment?

Any help apreciated :)

+3  A: 

In this line,

finn=((defined?(finn)) ? (finn+1):(0))

When you write finn=, it declares finn, and sets it to nil until the assignment occurs. Therefore, defined?(finn) returns true , so it attempts to execute finn+1, which is equivalent to nil+1, which results in the NoMethodError you mentioned above.

You may be looking for this:

finn ||= 0
finn += 1
John Douthat
ok - thanks for the explanationHow would you recomend to do it instead? There must be a more "rubyesq" way to do it...
zipizap
rubii's way is The Ruby Way(tm). Mine is a cheap facsimile ;)
John Douthat
Yours and @rubiii's answer can be combined, sort of: `finn = (finn || 0) + 1`
Wayne Conrad
thanks John, its understood now :)
zipizap
and thanks to rubiii and Wayne for the contributions :)
zipizap
+1  A: 

john is right. try:

finn = finn ? finn + 1 : 0
rubiii