Why don't $global and @instance variables need declaration?

D

David Garamond

Sorry if the answer is obvious, but I can't find a satisfactory or more
verbose explanation about this. The only thing I found is from the
Ruby's User Guide:

"As with globals, instance variables have the nil value until they are
initialized. Instance variables of ruby do not need declaration. This
implies a flexible structure of objects. In fact, each instance variable
is dynamically appended to an object when it is first referenced."

Could someone explain the above? How is it more flexible? Also, how do
we differentiate between an unitialized global/instance variable and a
variable that has explicitly been set to 'nil'?
 
R

Robert Klemme

David Garamond said:
Sorry if the answer is obvious, but I can't find a satisfactory or more
verbose explanation about this. The only thing I found is from the
Ruby's User Guide:

"As with globals, instance variables have the nil value until they are
initialized. Instance variables of ruby do not need declaration. This
implies a flexible structure of objects. In fact, each instance variable
is dynamically appended to an object when it is first referenced."

Could someone explain the above? How is it more flexible?

You don't need the declaration. That saves typing and also you can add
them at runtime as you like:

irb(main):003:0> class Foo
irb(main):004:1> def set(name, val)
irb(main):005:2> instance_eval "#{name} = val"
irb(main):006:2> end
irb(main):007:1>
irb(main):008:1* def get(name)
irb(main):009:2> instance_eval name
irb(main):010:2> end
irb(main):011:1> end
=> nil
irb(main):012:0>
irb(main):013:0* f=Foo.new
=> #<Foo:0x101724a0>
irb(main):014:0> f.set "@foo", "bar"
=> "bar"
irb(main):015:0> f.get "@foo"
=> "bar"
irb(main):016:0> f.set "@hello", "world"
=> "world"
irb(main):017:0> f.instance_variables
=> ["@hello", "@foo"]
irb(main):018:0>

If you would need to declare globals then you either need to include a
declaration for each global you need or you had to add code in each place
that would do the declaration on the fly when needed. That's tedious and
error prone.
Also, how do
we differentiate between an unitialized global/instance variable and a
variable that has explicitly been set to 'nil'?

Typically you don't. There are certain situations where you can use
"defined?" but these are rare. AFAIK it's seldom used. The more usable
option is to use "global_variables":

irb(main):002:0> puts global_variables
$-w
$stderr
$LOAD_PATH
$<
$-0
$+
$-p
$$
$-i
$deferr
$~
$!
$-v
$stdout
$_
$-K
$-F
$SAFE
$*
$-I
$/
$'
$-d
$FILENAME
$defout
$@
$VERBOSE
$stdin
$.
$KCODE
$;
$binding
$0
$:
$,
$`
$DEBUG
$>
$-a
$"
$\
$=
$-l
$?
$&
=> nil
irb(main):003:0>

Regards

robert
 
D

David Garamond

Robert said:
You don't need the declaration. That saves typing and also you can add
them at runtime as you like:

Oops, my bad English strikes again. The question should have been: "why
don't $global and @instance need *initialization* (i.e. they are already
preset to nil)?" In other words, why does it behave like this?


irb(main):001:0> a
NameError: undefined local variable or method `a' for main:Object
from (irb):1
irb(main):002:0> a=nil; a
=> nil
irb(main):003:0> $a
=> nil
irb(main):004:0> @a
=> nil


... and not like this?


irb(main):001:0> a
NameError: undefined local variable or method `a' for main:Object
from (irb):1
irb(main):002:0> a=nil; a
=> nil
irb(main):003:0> $a
NameError: undefined global variable `$a'
from (irb):3
irb(main):004:0> $a=nil; $a
=> nil
irb(main):005:0> @a
NameError: undefined instance variable `@a'
from (irb):5
irb(main):006:0> @a=nil; @a
=> nil
 
T

ts

D> NameError: undefined local variable or method `a' for main:Object
^^^^^^^^^^^^^^^^^^^^^^^^

The message is important : ruby don't know if it's a variable or a method
and can't initialize it.


Guy Decoux
 
D

David Garamond

ts said:
D> NameError: undefined local variable or method `a' for main:Object
^^^^^^^^^^^^^^^^^^^^^^^^

The message is important : ruby don't know if it's a variable or a method
and can't initialize it.

I see. I thought Ruby's intention was to protect someone from making a
stupid mistake of using uninitialized variables (ala Python). But then I
remember Ruby has the -w switch, so I guess Ruby never enforces this and
just gives a warning.
 
D

David Garamond

David said:
I see. I thought Ruby's intention was to protect someone from making a
stupid mistake of using uninitialized variables (ala Python). But then I
remember Ruby has the -w switch, so I guess Ruby never enforces this and
just gives a warning.

Btw, what do people think of adding the following system hooks in Ruby:

Kernel::unitialized_global_variable_accessed
Kernel::unitialized_instance_variable_accessed

which can be used to implement the behaviour for instance and global
variables (i.e. raising NameError), but without breaking the current
behaviour.
 
T

ts

D> Btw, what do people think of adding the following system hooks in Ruby:

What are you trying to solve ?


Guy Decoux
 
D

David Garamond

ts said:
D> Btw, what do people think of adding the following system hooks in Ruby:
What are you trying to solve ?

Making Ruby raise NameError when an uninitialized global or instance
variable is accessed (just like when a new local variable is mentioned
without being assigned first).
 
R

Robert Klemme

David Garamond said:
Making Ruby raise NameError when an uninitialized global or instance
variable is accessed (just like when a new local variable is mentioned
without being assigned first).

Why do you need that? What about lazy init?

class Foo
def bar;@bar||={};end
end

f = Foo.new
f.bar["hello"] = "world"

.... or the common ad hoc init idiom?

class Bar
def add(name)
(@names||=[]) << name
end
end

b = Bar.new
b.add "hello"

Regards

robert
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,431
Messages
2,571,677
Members
48,796
Latest member
Greg L.

Latest Threads

Top