Metaprogramming surprise?

Here comes some simple meta code

class D
@@e=5
@@f = 10
@@g = 20
class << self
attr_reader :e
attr_accessor :g
end
def self.f
@@f
end

def show
print “\nshow @@e=”,@@e, " @@f=", @@f, " @@g=",@@g
print “\nshow self.class.e=”, self.class.e
print “\nshow self.class.f=”, self.class.f
print “\nshow self.class.g=”, self.class.g
end
end

D.g= 40
print "\nD.e= ",D.e
print "\nD.g= ",D.g
print "\nD.f= ",D.f
D.new.show
<<<<<<<<<<<<<<<<<<<<<<<<<<<

here is the result

D.e= nil
D.g= 40
D.f= 10
show @@e=5 @@f=10 @@g=20
show self.class.e=nil
show self.class.f=10
show self.class.g=40

I’would expect
D.e= 5
D.g= 40
D.f= 10
show @@e=5 @@f=10 @@g=40
show self.class.e=nil
show self.class.f=10
show self.class.g=40

so what’s wrong with my understanding, that

class D
@@e=5
class << self
attr_reader :e # <- why this does not refer to @@e
end
end

Artur M. wrote:

end
end
D.e= nil
D.f= 10
attr_reader :e # <- why this does not refer to @@e
end
end

sorry for the typo, I’would naturally expect
D.e= 5
D.g= 40
D.f= 10
show @@e=5 @@f=10 @@g=40
show self.class.e=5
show self.class.f=10
show self.class.g=40

On 10/17/06, Artur M. [email protected] wrote:

end
end
D.e= nil
D.f= 10
attr_reader :e # ← why this does not refer to @@e
end
end

There’s a difference between class variables (@@x) and singleton class
instance variables (self.class.@x). They are not the same thing.

Jan S. schrieb:

attr_accessor :g

end

D.g= 40
class << self
attr_reader :e # <- why this does not refer to @@e
end
end

There’s a difference between class variables (@@x) and singleton class
instance variables (self.class.@x). They are not the same thing.

OK, but why are they not the same???

I’m missing some kind of analogy, see the following code:

class E
def show; print "\noutput @e= ",@e; end
end

class F
def show; print "\noutput @@ff= ",@@ff; end
end

obj= E.new
class << obj
attr_accessor :e
end

class << F
attr_accessor :ff
end

F.ff= “should be @@ff?, but is not”
obj.e= “should be @e, and really is”

obj.show
F.new.show

output @e= should be @e, and really is
test.rb:33:in `show’: uninitialized class variable @@ff in F
(NameError)
from test.rb:50

Hi –

On Tue, 17 Oct 2006, Artur M. wrote:

so what’s wrong with my understanding, that

class D
@@e=5
class << self
attr_reader :e # <- why this does not refer to @@e
end
end

attr_reader :e is equivalent to:

def e
@e
end

The class variable @@e is not involved at all.

David

On Tue, 17 Oct 2006, Artur M. wrote:

OK, but why are they not the same???

because the solve different problems:

 harp:~ > cat a.rb
 class A
   @@class_var = "one for all descendants"
   @class_instance_var = "one per class"

   class << self
     attr_accessor "class_instance_var"

     def class_var() @@class_var end
     def class_var=(val) @@class_var = val end
   end

   attr_accessor "instance_var"

   def initialize s
     @instance_var = "one per instance (#{ s })"
   end
 end

 class B < A
 end


 a = A.new 'a'
 b = B.new 'b'

 require "yaml"

 puts "---"
 y "a.instance_var"       => a.instance_var
 y "b.instance_var"       => b.instance_var
 y "A.class_var"          => A.class_var
 y "B.class_var"          => B.class_var
 y "A.class_instance_var" => A.class_instance_var
 y "B.class_instance_var" => B.class_instance_var

 B.class_instance_var = "this one is just for B"

 puts "---"
 y "a.instance_var"       => a.instance_var
 y "b.instance_var"       => b.instance_var
 y "A.class_var"          => A.class_var
 y "B.class_var"          => B.class_var
 y "A.class_instance_var" => A.class_instance_var
 y "B.class_instance_var" => B.class_instance_var


 harp:~ > ruby a.rb
 ---
 a.instance_var: one per instance (a)
 b.instance_var: one per instance (b)
 A.class_var: one for all descendants
 B.class_var: one for all descendants
 A.class_instance_var: one per class
 B.class_instance_var:
 ---
 a.instance_var: one per instance (a)
 b.instance_var: one per instance (b)
 A.class_var: one for all descendants
 B.class_var: one for all descendants
 A.class_instance_var: one per class
 B.class_instance_var: this one is just for B

regards

-a

Artur M. wrote:

Jan S. schrieb:

There’s a difference between class variables (@@x) and singleton class
instance variables (self.class.@x). They are not the same thing.

OK, but why are they not the same???

A class variable is not an instance variable of any instance, not even a
class. It has its own special semantics of sharing that is quite
different from the privacy of an instance variable.

class A
@@y = “A y”
end

class B < A
@@x = “B x”
@@y = “B y”
end

class A
@@x = “A x”
end

class A
p [@@x, @@y] # ==> [“A x”, “B y”]
end

class B
p [@@x, @@y] # ==> [“B x”, “B y”]
end

Note that the fact that @@x was assigned first in a subclass makes it
distinct in A and B, but the fact that @@y was assigned first in the
superclass makes it shared.

Artur M. wrote:

I hope this is the correct naming for this variables

That seems correct.

Joel VanderWerf schrieb:

different from the privacy of an instance variable.
class A

Note that the fact that @@x was assigned first in a subclass makes it
distinct in A and B, but the fact that @@y was assigned first in the
superclass makes it shared.


vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407
thanx, now I understand.

I also recovered my analogy

class E
def show; print "\noutput show= ",@e; end
end

class F
def self.show; print "\noutput F.show= ",@f; end
def show
print "\noutput @f= ",@f
end
end

obj= E.new
class << obj
attr_accessor :e
end

class << F
attr_accessor :f
end

F.f= “should be ‘F.@f’, and really is”
obj.e= “should be @e, and really is”

obj.show
F.show
F.new.show

<<<<<<<<<<<<<<<<<<<

results in (the now expected)

output show= should be @e, and really is
output E.show= should be ‘F.@f’, and really is
output @f= nil

So one has to distinguish between using a ‘class variable’ and
‘class instance variable’:

class A
@@class_variable
@class_instance_variable
def initialize
@instance_variable
end
end

I hope this is the correct naming for this variables

On Oct 17, 2006, at 2:02 PM, John W. Long wrote:

Jan S. wrote:

There’s a difference between class variables (@@x) and singleton
class
instance variables (self.class.@x). They are not the same thing.

Class variables seem to trip up everyone learning Ruby, yet
proficient Ruby programmers rarely seem to use them. Are they really
worth the trouble? I’ve yet to feel the need to use them but maybe
that is just me.

Any chance that class variables will disappear in Ruby 2.0? I’m only
half joking.

Gary W.

Jan S. wrote:

There’s a difference between class variables (@@x) and singleton class
instance variables (self.class.@x). They are not the same thing.

More on this here:

http://wiseheartdesign.com/articles/2006/09/22/class-level-instance-variables/

On 10/18/06, [email protected] [email protected] wrote:

worth the trouble? I’ve yet to feel the need to use them but maybe
that is just me.

Yeah, I use class instance variables all the time but it’s rare for me
to need a class variable.

If i want to share something with my descendants, it’s not often that
I want that information to change, so a class level method or constant
usually does the trick for me.

Still, i imagine that there exist needs for them in some way or
another. I remember using them in a few places, though I can’t
remember for what. :wink:

As mentioned earlier in the thread, If we treat instance variables as
instance variables no matter where we define them, but just pay
attention to how they are accessed, I think it gets much less
confusing.

I don’t think i’ve ever used a global variable in Ruby aside from the
builtins, but it doesn’t necessarily mean they need to go away :slight_smile:

On 10/18/06, [email protected] [email protected] wrote:

Class variables seem to trip up everyone learning Ruby, yet
proficient Ruby programmers rarely seem to use them. Are they really
worth the trouble? I’ve yet to feel the need to use them but maybe
that is just me.

Any chance that class variables will disappear in Ruby 2.0? I’m only
half joking.

I use them fairly frequently, and have never been tripped up by them.
They seem like a pretty straightforward idea to me. I tend to use them
for “config-ish” things in the class, which would need to have the same
value in all instances of the class.

On Oct 20, 2006, at 5:03 PM, Garance A Drosehn wrote:

I use them fairly frequently, and have never been tripped up by them.
They seem like a pretty straightforward idea to me. I tend to use
them
for “config-ish” things in the class, which would need to have the
same
value in all instances of the class.

Is there a particular reason you chose class variables versus regular
old instance variables on the class object? Is it just because the
@@var notation makes it easier to access the variables (i.e., you don’t
need to define class level getter/setters for the class object instance
variables)?

Gary W.