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 Merke wrote:

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

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

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

···

On 10/17/06, Artur Merke <am@artbot.de> wrote:

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

Hi --

···

On Tue, 17 Oct 2006, Artur Merke 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

--
                   David A. Black | dblack@wobblini.net
Author of "Ruby for Rails" [1] | Ruby/Rails training & consultancy [3]
DABlog (DAB's Weblog) [2] | Co-director, Ruby Central, Inc. [4]
[1] Ruby for Rails | [3] http://www.rubypowerandlight.com
[2] http://dablog.rubypal.com | [4] http://www.rubycentral.org

Jan Svitok schrieb:

> 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

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

···

On 10/17/06, Artur Merke <am@artbot.de> wrote:

Jan Svitok 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/

···

--
John Long
http://wiseheartdesign.com
http://radiantcms.org

Artur Merke wrote:

Jan Svitok 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.

···

--
       vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

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

···

On Tue, 17 Oct 2006, Artur Merke wrote:

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

     ---
     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
--
my religion is very simple. my religion is kindness. -- the dalai lama

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 Wright

···

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

Jan Svitok wrote:

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

Joel VanderWerf schrieb:

Artur Merke wrote:
> Jan Svitok 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.

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

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, gwtmp01@mac.com <gwtmp01@mac.com> wrote:

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

> Jan Svitok 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.

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 10/18/06, gwtmp01@mac.com <gwtmp01@mac.com> 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.

--
Garance Alistair Drosehn = drosihn@gmail.com
Senior Systems Programmer
Rensselaer Polytechnic Institute; Troy, NY; USA

Artur Merke wrote:

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

That seems correct.

···

--
       vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

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 Wright

···

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.