Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Ruby > Class Variable Confusion

Reply
Thread Tools

Class Variable Confusion

 
 
gwtmp01@mac.com
Guest
Posts: n/a
 
      12-21-2006
I generally avoid class variables but at the last meeting of the New
Haven Ruby Brigade a simple question about them led to a long
discussion and irb session that only served to confuse us all more.

I'm hoping someone on the list can shed some light on a couple of
issues that were raised:

>> class A
>> @@avar = 'hello'
>> end

=> "hello"
>> A.class_variables

=> ["@@avar"]
>> A.class_eval { puts @@avar }

NameError: uninitialized class variable @@avar in Object
from (irb):5
from (irb):5
>> class A
>> puts @@avar
>> end

hello
=> nil
>> class A
>> def get_avar
>> @@avar
>> end
>> end

=> nil
>> a = A.new

=> #<A:0x4ba360>
>> a.get_avar

=> "hello"
>> a.instance_eval { puts @@avar }

NameError: uninitialized class variable @@avar in Object
from (irb):16
from (irb):16
>>



It seems like a block evaluated by class_eval should have access to
the class variables. Similarly, it seems like if an instance method
(get_avar in the example) has access to the class variable then the
variable should also be visible via instance_eval.

In both examples above (class_eval and instance_eval) it seems like
the class variable @@avar is being looked up relative to the
top_level object and not relative to the class and instance objects
respectively.


What am I missing?

Gary Wright


 
Reply With Quote
 
 
 
 
dblack@wobblini.net
Guest
Posts: n/a
 
      12-21-2006
Hi --

On Fri, 22 Dec 2006, http://www.velocityreviews.com/forums/(E-Mail Removed) wrote:

> I generally avoid class variables but at the last meeting of the New Haven
> Ruby Brigade a simple question about them led to a long discussion and irb
> session that only served to confuse us all more.
>
> I'm hoping someone on the list can shed some light on a couple of issues that
> were raised:
>
>>> class A
>>> @@avar = 'hello'
>>> end

> => "hello"
>>> A.class_variables

> => ["@@avar"]
>>> A.class_eval { puts @@avar }

> NameError: uninitialized class variable @@avar in Object
> from (irb):5
> from (irb):5
>>> class A
>>> puts @@avar
>>> end

> hello
> => nil
>>> class A
>>> def get_avar
>>> @@avar
>>> end
>>> end

> => nil
>>> a = A.new

> => #<A:0x4ba360>
>>> a.get_avar

> => "hello"
>>> a.instance_eval { puts @@avar }

> NameError: uninitialized class variable @@avar in Object
> from (irb):16
> from (irb):16
>>>

>
>
> It seems like a block evaluated by class_eval should have access to the
> class variables. Similarly, it seems like if an instance method (get_avar in
> the example) has access to the class variable then the variable should also
> be visible via instance_eval.
>
> In both examples above (class_eval and instance_eval) it seems like the
> class variable @@avar is being looked up relative to the top_level object
> and not relative to the class and instance objects respectively.
>
>
> What am I missing?


You had me at "I generally avoid class variables"

Here's another one you'll like:

@@avar = 1
class A
@@avar = "hello"
end
puts @@avar # => hello

A.class_eval { puts @@avar } # => hello

I love Ruby madly, but (or "therefore"? I would be happy never to
see another class variable again. The confusingness-to-usefulness
ratio is extremely high.


David

--
Q. What's a good holiday present for the serious Rails developer?
A. RUBY FOR RAILS by David A. Black (http://www.manning.com/black)
aka The Ruby book for Rails developers!
Q. Where can I get Ruby/Rails on-site training, consulting, coaching?
A. Ruby Power and Light, LLC (http://www.rubypal.com)

 
Reply With Quote
 
 
 
 
David Goodlad
Guest
Posts: n/a
 
      12-21-2006
On 12/21/06, Chunyun Zhao <(E-Mail Removed)> wrote:
> Seems it works perfectly fine when evaluating the string instead of block:
>
> class A
> @@avar = "hello"
> end
>
> A.class_eval("puts @@avar") # => hello
> A.class_eval { puts @@avar } #=> throws NameError
>
> Very interestsing, anyone could explain it?


Since the block acts as a closure, the class variable references seem
to be bound to its original scope; iirc, the only variable types that
will change scope in the context of a class_eval (which changes the
value of 'self') are instance variables. That's why the string will
evaluate correctly, while the block fails to find the class variable.

I'm not an expert, but this has been my experience.

Dave

>
> On 12/21/06, (E-Mail Removed) <(E-Mail Removed)> wrote:
> >
> > Hi --
> >
> > On Fri, 22 Dec 2006, (E-Mail Removed) wrote:
> >
> > > I generally avoid class variables but at the last meeting of the New

> > Haven
> > > Ruby Brigade a simple question about them led to a long discussion and

> > irb
> > > session that only served to confuse us all more.
> > >
> > > I'm hoping someone on the list can shed some light on a couple of issues

> > that
> > > were raised:
> > >
> > >>> class A
> > >>> @@avar = 'hello'
> > >>> end
> > > => "hello"
> > >>> A.class_variables
> > > => ["@@avar"]
> > >>> A.class_eval { puts @@avar }
> > > NameError: uninitialized class variable @@avar in Object
> > > from (irb):5
> > > from (irb):5
> > >>> class A
> > >>> puts @@avar
> > >>> end
> > > hello
> > > => nil
> > >>> class A
> > >>> def get_avar
> > >>> @@avar
> > >>> end
> > >>> end
> > > => nil
> > >>> a = A.new
> > > => #<A:0x4ba360>
> > >>> a.get_avar
> > > => "hello"
> > >>> a.instance_eval { puts @@avar }
> > > NameError: uninitialized class variable @@avar in Object
> > > from (irb):16
> > > from (irb):16
> > >>>
> > >
> > >
> > > It seems like a block evaluated by class_eval should have access to the
> > > class variables. Similarly, it seems like if an instance

> > method (get_avar in
> > > the example) has access to the class variable then the variable should

> > also
> > > be visible via instance_eval.
> > >
> > > In both examples above (class_eval and instance_eval) it seems like the
> > > class variable @@avar is being looked up relative to the top_level

> > object
> > > and not relative to the class and instance objects respectively.
> > >
> > >
> > > What am I missing?

> >
> > You had me at "I generally avoid class variables"
> >
> > Here's another one you'll like:
> >
> > @@avar = 1
> > class A
> > @@avar = "hello"
> > end
> > puts @@avar # => hello
> >
> > A.class_eval { puts @@avar } # => hello
> >
> > I love Ruby madly, but (or "therefore"? I would be happy never to
> > see another class variable again. The confusingness-to-usefulness
> > ratio is extremely high.
> >
> >
> > David
> >
> > --
> > Q. What's a good holiday present for the serious Rails developer?
> > A. RUBY FOR RAILS by David A. Black (http://www.manning.com/black)
> > aka The Ruby book for Rails developers!
> > Q. Where can I get Ruby/Rails on-site training, consulting, coaching?
> > A. Ruby Power and Light, LLC (http://www.rubypal.com)
> >
> >

>
>



--
Dave Goodlad
(E-Mail Removed) or (E-Mail Removed)
http://david.goodlad.ca/

 
Reply With Quote
 
gwtmp01@mac.com
Guest
Posts: n/a
 
      12-22-2006

On Dec 21, 2006, at 4:44 PM, (E-Mail Removed) wrote:
> Here's another one you'll like:
>
> @@avar = 1
> class A
> @@avar = "hello"
> end
> puts @@avar # => hello
>
> A.class_eval { puts @@avar } # => hello


Let's see if I understand what is going on:

When @@var is set to 1 at the top-level it is associated with the
class Object (a feature of the top-level context) and as such @@var
then becomes visible to the entire class hierarchy rooted at Object
(i.e., all objects). When @@avar is evaluated in the class A block,
Ruby finds @@var already defined for the hierarchy (because A is a
subclass of Object). So in this example all three occurrences of
@@avar are associated with the same class variable. If you reverse
the assignments:

class A
@@avar = "hello"
end
@@avar = 1

A.class_eval { puts @@avar } # => 1
class A
puts @@avar # => hello
end

There are now two distinct class variables named @@avar, one is
associated with Object and another is associated with class A and
shadows the one associated with Object.

I still don't understand why class_eval/instance_eval don't affect
the resolution of class variables in a manner analogous to how they
affect the resolution of instance variables. Is this by design or
accident?


Gary Wright




 
Reply With Quote
 
dblack@wobblini.net
Guest
Posts: n/a
 
      12-22-2006
Hi --

On Fri, 22 Dec 2006, (E-Mail Removed) wrote:

> class A
> @@avar = "hello"
> end
> @@avar = 1
>
> A.class_eval { puts @@avar } # => 1
> class A
> puts @@avar # => hello
> end
>
> There are now two distinct class variables named @@avar, one is associated
> with Object and another is associated with class A and shadows the one
> associated with Object.


Yes -- basically, if you create the class variable in the subclass
first, then it's different from the one in the superclass. Mind you,
a lot of this is scheduled to change in 2.0. I fear, though that the
confusion caused by class variables will persist. A class variable is
going to be (as I understand it) more similar to an instance variable
than it is now, but with visibility to instances of the class. A lot
of the problem with class variables is that they cloud the matter of
classes being objects and having their own instance variables. I'm
not sure whether these changes will change that.

(When I say they cloud it, I'm basing this on six years of watching
person after person after person have trouble grasping this area of
Ruby, and it's always something like, "Wait -- doesn't a class have
*class* variables? If they're analogous to instance variables for
instances, then what are they?" It can be explained, of course (I've
done it many times but there's definitely something in the
behavior that makes this harder to get than most other language
features.)

> I still don't understand why class_eval/instance_eval don't affect the
> resolution of class variables in a manner analogous to how they affect the
> resolution of instance variables. Is this by design or accident?


See David Goodlad's explanation; I think it's by design. class_eval
brings about a scope that's like a 'class' block in some ways but not
in others. The surrounding class and local variables can permeate
their way in.


David

--
Q. What's a good holiday present for the serious Rails developer?
A. RUBY FOR RAILS by David A. Black (http://www.manning.com/black)
aka The Ruby book for Rails developers!
Q. Where can I get Ruby/Rails on-site training, consulting, coaching?
A. Ruby Power and Light, LLC (http://www.rubypal.com)

 
Reply With Quote
 
Rob Muhlestein
Guest
Posts: n/a
 
      01-05-2007
(E-Mail Removed) wrote:
> You had me at "I generally avoid class variables"
> ...snip...
> I love Ruby madly, but (or "therefore"? I would be happy never to
> see another class variable again. The confusingness-to-usefulness
> ratio is extremely high.


David and gang, thanks for pulling me out of denial.

[Here's a blog post about my facing reality, finally:
http://rob.muhlestein.net/2007/01/ru...go-there.html]

Rob

 
Reply With Quote
 
Gregory Brown
Guest
Posts: n/a
 
      01-05-2007
On 12/21/06, (E-Mail Removed) <(E-Mail Removed)> wrote:

> You had me at "I generally avoid class variables"
>
> Here's another one you'll like:
>
> @@avar = 1
> class A
> @@avar = "hello"
> end
> puts @@avar # => hello
>
> A.class_eval { puts @@avar } # => hello
>
> I love Ruby madly, but (or "therefore"? I would be happy never to
> see another class variable again. The confusingness-to-usefulness
> ratio is extremely high.


Wow David, that is scary.

 
Reply With Quote
 
Rob Muhlestein
Guest
Posts: n/a
 
      01-05-2007

Rob Muhlestein wrote:
> (E-Mail Removed) wrote:
> > You had me at "I generally avoid class variables"
> > ...snip...
> > I love Ruby madly, but (or "therefore"? I would be happy never to
> > see another class variable again. The confusingness-to-usefulness
> > ratio is extremely high.

>
> David and gang, thanks for pulling me out of denial.
>
> [Here's a blog post about my facing reality, finally:
> http://rob.muhlestein.net/2007/01/ru...go-there.html]


After reading the comments in the response it is probably worth
mentioning in this thread that class *variable* scope inheritance is
changing between 1.8 and 1.9/2.0 (as noted in the pickax). I ran an irb
confirmation of this and posted results there to make sure.

 
Reply With Quote
 
Gregory Brown
Guest
Posts: n/a
 
      01-05-2007
On 1/5/07, Rob Muhlestein <(E-Mail Removed)> wrote:
> (E-Mail Removed) wrote:
> > You had me at "I generally avoid class variables"
> > ...snip...
> > I love Ruby madly, but (or "therefore"? I would be happy never to
> > see another class variable again. The confusingness-to-usefulness
> > ratio is extremely high.

>
> David and gang, thanks for pulling me out of denial.
>
> [Here's a blog post about my facing reality, finally:
> http://rob.muhlestein.net/2007/01/ru...go-there.html]


I blogged it too, though mine is mostly just a quick paste of the two
bits of code from David and Gary, and a link to your blog entry. My
NubyGems series is usually like that, a big chunk of code from an IRB
session meant to make people go 'whoa, yeah, that does suck'

http://www.oreillynet.com/ruby/blog/..._variab_1.html

 
Reply With Quote
 
Brock Lee
Guest
Posts: n/a
 
      01-05-2007
So, would it be fair to say that you won't run into difficulties with
class variables (denoted with @@) if:

a. you assign class variables in the superclass before assigning
them in the sublcass, and
b. you don't expect class_eval to provide access to them?

Or are there other areas of confusion?

Thanks,

Brock

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Class variable confusion Keith Salisbury Ruby 5 04-23-2009 05:05 PM
confusion about variable scope in a class gyro Python 1 02-14-2009 04:37 PM
"Variable variable name" or "variable lvalue" mfglinux Python 11 09-12-2007 03:08 AM
Nested Class, Member Class, Inner Class, Local Class, Anonymous Class E11 Java 1 10-12-2005 03:34 PM
How do I scope a variable if the variable name contains a variable? David Filmer Perl Misc 19 05-21-2004 03:55 PM



Advertisments