I have a question, because in most serious sources I read, all say the same No variable is ever declared in Ruby
, but still I have doubts, because according to what I was taught in my university implicit declaration is when a variable is created via allocation, where you can specify the type of a variable through conventions established in the language.
This contrasts with explicit declaration, when the data type specified in its declaration, like C… or at least that’s what I understood.
So I was taught wrong?, or I misunderstood something?
What they said:
No variable is ever declared in Ruby
What they meant:
There is no keyword defining a line of code as declaring a variable. Variables can just be used, and at worst are
nil
.
If you have not previously assigned a value to a variable in Ruby, it becomes nil
as soon as you retrieve its value.
class Foo
def bar
@bar
end
end
a = Foo.new
puts a.bar
You weren’t taught wrong. They just describe it in a non academic way.
1
Different variables behave differently in Ruby, but none of them need explicit declaration.
The most interesting behavior is for local variables: Ruby allows you to leave off the receiver for a message send to self
(self
is the implicit receiver), so foo()
is the same thing as self.foo()
, and it also allows you to leave off the argument list if there are no arguments, so foo.bar
is the same thing as foo.bar()
; putting the two together, we get that foo
is the same thing as self.foo()
, i.e. a message send without arguments to the implicit receiver self
. It could, however, also be a reference to the local variable foo
. This ambiguity is resolved the following way: foo
is interpreted as a message send, unless an assignment to foo
has been parsed (but not necessarily executed) before, then from that point on it is interpreted as a local variable.
This is the closest thing Ruby has to variable declaration:
foo
# NameError: undefined local variable or method `foo'
defined?(foo)
# => nil
def foo; 23 end
foo
# => 23
defined?(foo)
# => 'method'
methods
# => [:foo, …]
if false then foo = 42 end
foo
# => nil
defined?(foo)
# => 'local-variable'
local_variables
# => [:foo]
Note that the NameError
is not raised because the local variable is undefined, but because Ruby doesn’t know what to make of the expression: is it a local variable or a method call?
Instance variables and global variables behave similarly, they evaluate to nil
even if they are not defined:
@foo
# => nil
defined?(@foo)
# => nil
@foo = 42
@foo
# => 42
defined?(@foo)
# => 'instance-variable'
instance_variables
# => [:@foo]
$foo
# => nil
defined?($foo)
# => nil
$foo = 42
$foo
# => 42
defined?($foo)
# => 'global-variable'
global_variables
# => [:$foo, …]
Class hierarchy variables and constants behave differently, they raise NameError
if they are not defined:
@@foo
# NameError
defined?(@@foo)
# => nil
@@foo = 42
@@foo
# => 42
defined?(@@foo)
# => 'class-variable'
self.class.class_variables
# => [:@@foo]
FOO
# NameError
defined?(FOO)
# => nil
FOO = 42
FOO
# => 42
defined?(FOO)
# => 'constant'
self.class.constants
# => [:FOO]