Sai
Sai

Reputation: 7209

Why do undeclared Ruby local, instance, class, & global variables have different behavior?

Some undeclared variables are nil, some throw an error. How come?

$ irb
1.9.3p0 :001 > asdf  # local
NameError: undefined local variable or method `asdf' for main:Object
from (irb):1
from /Users/saizai/.rvm/rubies/ruby-1.9.3-p0/bin/irb:16:in `<main>'
1.9.3p0 :002 >@asdf # instance
=> nil 
1.9.3p0 :003 >@@asdf # class
NameError: uninitialized class variable @@asdf in Object
from (irb):3
from /Users/saizai/.rvm/rubies/ruby-1.9.3-p0/bin/irb:16:in `<main>'
1.9.3p0 :004 > $asdf # global
=> nil

Upvotes: 4

Views: 852

Answers (1)

Charles Caldwell
Charles Caldwell

Reputation: 17169

Class variables must always be assigned or else they will return a NameError when you attempt to use them. I do not currently have the details as to why this is.

Instance and Global variables will return nil even if they are not assigned. However, they will raise a warning if you run the script with the -w flag.

I do, however, have the answer in regards to the local variables. The reason local variables act like this comes in the fact that they do not have any punctuation in front of them. This means the variable could be either a variable or a method call (since Ruby does not require () after a method call with no parameters).

something # could be a variable named 'something' or a method called 'something()'

If there is no value assigned to something variable then the Ruby interpreter assumes it is a method invocation. If there is no method by that name then it raises NameError. That is why you will get this message:

NameError: undefined local variable or method 'something' for main:Object
     from (irb):1
     from path/to/Ruby/bin/irb:12 in '<main>'

So, it is important for the Ruby interpreter to treat local variables in this manner just in case it is actually a method you are referring to.

As an interesting side note:

There is one quirk—a variable comes into existence when the Ruby interpreter sees an assignment expression for that variable. This is the case even if that assignment is not actually executed. A variable that exists but has not been assigned a value is given the default value nil.

Which means that:

if false
   z = "Something"
end

z.nil? #=> true
never_assigned.nil? #=> NameError

The above quote is from The Ruby Programming Language by David Flanagan and Yukihiro Matsumoto section 4.2

Upvotes: 5

Related Questions