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


(David Garamond) #1

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’?

···


dave


(Robert) #2

“David Garamond” lists@zara.6.isreserved.com schrieb im Newsbeitrag
news:403DC272.10009@zara.6.isreserved.com

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

(David Garamond) #3

Robert Klemme wrote:

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:

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

···


dave


(ts) #4

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


(David Garamond) #5

ts wrote:

“D” == David Garamond lists@zara.6.isreserved.com writes:
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.

···


dave


(David Garamond) #6

David Garamond wrote:

ts wrote:

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.

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.

···


dave


(ts) #7

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

What are you trying to solve ?

Guy Decoux


(David Garamond) #8

ts wrote:

“D” == David Garamond lists@zara.6.isreserved.com writes:
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).

···


dave


(Robert) #9

“David Garamond” lists@zara.6.isreserved.com schrieb im Newsbeitrag
news:403E125E.1020506@zara.6.isreserved.com

ts wrote:

“D” == David Garamond lists@zara.6.isreserved.com writes:
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).

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

(David Garamond) #10

Robert Klemme wrote:

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?

Help in detecting typo?

def foo
@barbaz = …

@quux = 1 if @barrbaz != … # typo
end

···


dave