[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Defining a Class Accessor

James Gray

3/30/2005 2:53:00 PM

I was playing around with an idea in another thread and ran into a
surprise. Can anyone explain the following to me?

irb(main):015:0> class Module
irb(main):016:1> def cattr_accessor( *symbols )
irb(main):017:2> symbols.each do |sym|
irb(main):018:3* eval "def self.#{sym}( ) @@#{sym} end
irb(main):019:3" def self.#{sym}=( value ) @@#{sym} =
value end"
irb(main):020:3> end
irb(main):021:2> end
irb(main):022:1> end
=> nil
irb(main):023:0> class Accessor
irb(main):024:1> cattr_accessor :one, :two
irb(main):025:1> def self.fetch_one( )
irb(main):026:2> @@one
irb(main):027:2> end
irb(main):028:1> end
=> nil
irb(main):029:0> Accessor.one = "James"
=> "James"
irb(main):030:0> Accessor.two = "Gray"
=> "Gray"
irb(main):031:0> Accessor.one
=> "James"
irb(main):032:0> Accessor.two
=> "Gray"
irb(main):033:0> Accessor.fetch_one
NameError: uninitialized class variable @@one in Accessor
from (irb):26:in `fetch_one'
from (irb):33
from (null):0

Everything works as expected, save fetch_one(). Why does it not return
"James"?

Thanks.

James Edward Gray II



13 Answers

martinus

3/30/2005 3:10:00 PM

0

> Everything works as expected, save fetch_one(). Why does it not return
> "James"?

The problem is that the class variables are defined for Module, and not
for the class Accessor:


class Module
def cattr_accessor( *symbols )
symbols.each do |sym|
eval "def self.#{sym}() @@#{sym} end
def self.#{sym}=(value) @@#{sym} = value end"
end
end
end

class A
cattr_accessor :one
end

class B
cattr_accessor :one
end


A.one = 1; p A.one # prints 1
B.one = 42; p A.one # prints 42!



martinus

Patrick Hurley

3/30/2005 3:20:00 PM

0

On Wed, 30 Mar 2005 23:53:25 +0900, James Edward Gray II
<james@grayproductions.net> wrote:
> I was playing around with an idea in another thread and ran into a
> surprise. Can anyone explain the following to me?
>
> irb(main):015:0> class Module
> irb(main):016:1> def cattr_accessor( *symbols )
> irb(main):017:2> symbols.each do |sym|
> irb(main):018:3* eval "def self.#{sym}( ) @@#{sym} end
> irb(main):019:3" def self.#{sym}=( value ) @@#{sym} =
> value end"
> irb(main):020:3> end
> irb(main):021:2> end
> irb(main):022:1> end
> => nil
> irb(main):023:0> class Accessor
> irb(main):024:1> cattr_accessor :one, :two
> irb(main):025:1> def self.fetch_one( )
> irb(main):026:2> @@one
> irb(main):027:2> end
> irb(main):028:1> end
> => nil
> irb(main):029:0> Accessor.one = "James"
> => "James"
> irb(main):030:0> Accessor.two = "Gray"
> => "Gray"
> irb(main):031:0> Accessor.one
> => "James"
> irb(main):032:0> Accessor.two
> => "Gray"
> irb(main):033:0> Accessor.fetch_one
> NameError: uninitialized class variable @@one in Accessor
> from (irb):26:in `fetch_one'
> from (irb):33
> from (null):0
>
> Everything works as expected, save fetch_one(). Why does it not return
> "James"?
>
> Thanks.
>
> James Edward Gray II
>
>

I have been playing with this myself, your @@one is in Module not in
Accessor -- try changing your eval to class_eval:

class Module
def cattr_accessor( *symbols )
symbols.each do |sym|
self.class_eval <<EVAL
def self.#{sym}()
@@#{sym}
end

def self.#{sym}=( value )
@@#{sym} = value
end
EVAL
end
end
end


Florian Gross

3/30/2005 3:26:00 PM

0

James Edward Gray II wrote:

> I was playing around with an idea in another thread and ran into a
> surprise. Can anyone explain the following to me?
>
> irb(main):015:0> class Module
> irb(main):016:1> def cattr_accessor( *symbols )
> irb(main):017:2> symbols.each do |sym|
> irb(main):018:3* eval "def self.#{sym}( ) @@#{sym} end
> irb(main):019:3" def self.#{sym}=( value ) @@#{sym} =
> value end"
> irb(main):020:3> end
> irb(main):021:2> end
> irb(main):022:1> end

Do you really need to use @@variables? From my experience they tend to
cause trouble.

Robert Klemme

3/30/2005 3:43:00 PM

0


"James Edward Gray II" <james@grayproductions.net> schrieb im Newsbeitrag
news:07549561ed849e497e65fdc423a92c88@grayproductions.net...
>I was playing around with an idea in another thread and ran into a
>surprise. Can anyone explain the following to me?
>
> irb(main):015:0> class Module
> irb(main):016:1> def cattr_accessor( *symbols )
> irb(main):017:2> symbols.each do |sym|
> irb(main):018:3* eval "def self.#{sym}( ) @@#{sym} end
> irb(main):019:3" def self.#{sym}=( value ) @@#{sym} = value
> end"
> irb(main):020:3> end
> irb(main):021:2> end
> irb(main):022:1> end
> => nil
> irb(main):023:0> class Accessor
> irb(main):024:1> cattr_accessor :one, :two
> irb(main):025:1> def self.fetch_one( )
> irb(main):026:2> @@one
> irb(main):027:2> end
> irb(main):028:1> end
> => nil
> irb(main):029:0> Accessor.one = "James"
> => "James"
> irb(main):030:0> Accessor.two = "Gray"
> => "Gray"
> irb(main):031:0> Accessor.one
> => "James"
> irb(main):032:0> Accessor.two
> => "Gray"
> irb(main):033:0> Accessor.fetch_one
> NameError: uninitialized class variable @@one in Accessor
> from (irb):26:in `fetch_one'
> from (irb):33
> from (null):0
>
> Everything works as expected, save fetch_one(). Why does it not return
> "James"?

I'm a bit stunned, too. Maybe this is a hint:

?> Accessor.class_variables
=> []
>> Module.class_variables
=> ["@@one", "@@two"]

Although:
>> Accessor.class.ancestors
=> [Class, Module, Object, Kernel]

So, since Accessor is an instance of Class, both should be accessible IMO.
Weired...

For me it's one more reason to never use class variables. They are simply
too awkward.

Kind regards

robert


PS: But I'm curios, too, why this does not work.

James Gray

3/30/2005 5:14:00 PM

0

On Mar 30, 2005, at 9:20 AM, Patrick Hurley wrote:

> I have been playing with this myself, your @@one is in Module not in
> Accessor -- try changing your eval to class_eval:
>
> class Module
> def cattr_accessor( *symbols )
> symbols.each do |sym|
> self.class_eval <<EVAL
> def self.#{sym}()
> @@#{sym}
> end
>
> def self.#{sym}=( value )
> @@#{sym} = value
> end
> EVAL
> end
> end
> end

Makes sense. Thank you.

James Edward Gray II



James Gray

3/30/2005 5:20:00 PM

0

On Mar 30, 2005, at 9:44 AM, Robert Klemme wrote:

> I'm a bit stunned, too. Maybe this is a hint:
>
> ?> Accessor.class_variables
> => []
>>> Module.class_variables
> => ["@@one", "@@two"]
>
> Although:
>>> Accessor.class.ancestors
> => [Class, Module, Object, Kernel]


Right, because I put the code in Module. It makes sense, when you let
it sink in.


> So, since Accessor is an instance of Class, both should be accessible
> IMO. Weired...
>
> For me it's one more reason to never use class variables. They are
> simply too awkward.
>
> Kind regards
>
> robert
>
>
> PS: But I'm curios, too, why this does not work.

Just switching to class_eval(), to make sure the code is executed in
the right context fixes the issue.

James



Patrick Hurley

3/30/2005 5:45:00 PM

0

On Thu, 31 Mar 2005 02:13:59 +0900, James Edward Gray II
<james@grayproductions.net> wrote:
> Makes sense. Thank you.

Not a problem, I feel like less of a ruby newbie today :-)


Navindra Umanee

3/30/2005 5:47:00 PM

0

Florian Gross <flgr@ccan.de> wrote:
> Do you really need to use @@variables? From my experience they tend to
> cause trouble.

Could you explain why they would cause trouble?

Thanks,
Navin.


Florian Gross

3/30/2005 7:52:00 PM

0

Navindra Umanee wrote:

> Florian Gross <flgr@ccan.de> wrote:
>
>>Do you really need to use @@variables? From my experience they tend to
>>cause trouble.
>
> Could you explain why they would cause trouble?

I thought the original post would answer that well enough already, but
in my own Ruby experience I have so far being surprised when using them.
Why should they be used when you can use far simpler constructs with
clearer rules?

Generally they seem to be used most as a quick replacement for instance
variables when something goes wrong without further questioning or
actually finding the root of the problem. I've seen them used quite
frequently in this case:

module StackMixIn
def push(item)
@items << item
end

def pop()
@items.pop
end

# I'd like to initialize @items, but this will not work:
@items = []

# If I just replace every '@items' with '@@items' it will magically
# work. It's an obvious fix. It must be in Ruby exactly as a fix for
# this kind of situation.
end

(And yes, I know that they are going to be simplified in Rite, but I'm
not sure if that is going to make them completely non-surprising to most
people...)

Navindra Umanee

3/30/2005 11:22:00 PM

0

Florian Gross <flgr@ccan.de> wrote:
> I thought the original post would answer that well enough already, but

Well, someone clarified what the problem was... he was assigning to
the class variables for Module instead of for the class itself. I
guess "self" is what is confusing.

> in my own Ruby experience I have so far being surprised when using them.
> Why should they be used when you can use far simpler constructs with
> clearer rules?

Well, the idea is to have shared storage for all objects of a
particular class, right? Class variables fit exactly that
requirement. I'm not sure which simpler constructs you're referring
to in this context... but perhaps I'm still too much in the Java
mindset.

Cheers,
Navin.