metaprogramming surprise?

A

Artur Merke

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
 
A

Artur Merke

Artur said:
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
 
J

Jan Svitok

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

dblack

Hi --

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 | (e-mail address removed)
Author of "Ruby for Rails" [1] | Ruby/Rails training & consultancy [3]
DABlog (DAB's Weblog) [2] | Co-director, Ruby Central, Inc. [4]
[1] http://www.manning.com/black | [3] http://www.rubypowerandlight.com
[2] http://dablog.rubypal.com | [4] http://www.rubycentral.org
 
A

Artur Merke

Jan said:
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
 
J

Joel VanderWerf

Artur said:
Jan Svitok schrieb: ...

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

ara.t.howard

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
 
A

Artur Merke

Joel said:
Artur said:
Jan Svitok schrieb: ..

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

Joel VanderWerf

Artur said:
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.
 
G

gwtmp01

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
 
G

Gregory Brown

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.

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. ;)

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 :)
 
G

Garance A Drosehn

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

gwtmp01

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 Wright
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,215
Messages
2,571,113
Members
47,713
Latest member
LeliaB1379

Latest Threads

Top