Class variable leading a double life

Can someone please explain why the @var variable leads a double life? One
for instances and one for the class itself?

class Test
def Test.inc
  @var ||= 0
  @var += 1
end

def inc
  @var ||= 0
  @var += 1
end
end

puts Test.inc

x = Test.new
puts x.inc

y = Test.new
puts y.inc

···

#-------------

puts Test.inc
puts x.inc
puts y.inc

Can someone please explain why the @var variable leads a double life? One
for instances and one for the class itself?

@var refers to an instance variable of the current "self" object.

class Test
def Test.inc
  @var ||= 0
  @var += 1
end

Here self is Test.

def inc
  @var ||= 0
  @var += 1
end
end

And here, self is an instance of Test. Two different objects, two different variables.

puts Test.inc

x = Test.new
puts x.inc

y = Test.new
puts y.inc

#-------------

puts Test.inc
puts x.inc
puts y.inc

If you want it to be the same variable in both places, you need a class variable:

class Test
@@var = 0

def Test.inc
   @@var += 1
end

def inc
   @@var += 1
end

puts Test.inc

x = Test.new
puts x.inc

y = Test.new
puts y.inc

···

On Jul 2, 2005, at 9:55 AM, Amarison wrote:

#-------------

puts Test.inc
puts x.inc
puts y.inc

Hope that helps.

James Edward Gray II

James Edward Gray II wrote:

Can someone please explain why the @var variable leads a double life? One
for instances and one for the class itself?

@var refers to an instance variable of the current "self" object.

class Test
def Test.inc
  @var ||= 0
  @var += 1
end

Here self is Test.

I thought that Test.inc was a class method that could be called without ever instantiating an object of class Test, and that therefore there would be no "self". Are you saying that Test is not just a class, but is also an instance of some other class? I don't understand, but then I'm just a newbie to Ruby.

···

On Jul 2, 2005, at 9:55 AM, Amarison wrote:

def inc
  @var ||= 0
  @var += 1
end
end

And here, self is an instance of Test. Two different objects, two different variables.

puts Test.inc

x = Test.new
puts x.inc

y = Test.new
puts y.inc

#-------------

puts Test.inc
puts x.inc
puts y.inc

If you want it to be the same variable in both places, you need a class variable:

class Test
@@var = 0

def Test.inc
  @@var += 1
end

def inc
  @@var += 1
end

puts Test.inc

x = Test.new
puts x.inc

y = Test.new
puts y.inc

#-------------

puts Test.inc
puts x.inc
puts y.inc

Hope that helps.

James Edward Gray II

James Edward Gray II wrote:

If you want it to be the same variable in both places, you need a class variable:

class Test
@@var = 0

...

James Edward Gray II

OK, now I'm confused. I had thought that class variables were just instance variables of the Test object, but it seems that the case is much weirder than that. (Why?)

class Test
  @fun = "hello"
  @@fun = 5
  def initialize
    p @fun
    p @@fun
    @fun = "blah"
    @@fun = "bloo"
  end
  def fun
    p @fun
    p @@fun
  end
end
def Test.fun
  p @fun
  p @@fun
  @fun = "bing"
  @@fun = "bong"
end

irb(main):021:0> Test.fun
"hello"
NameError: uninitialized class variable @@fun in Object
        from (irb):17:in `fun'
        from (irb):21

irb(main):022:0> t = Test.new
nil
5
=> #<Test:0x2aba608 @fun="blah">

irb(main):023:0> Test.fun
"hello"
NameError: uninitialized class variable @@fun in Object
        from (irb):17:in `fun'
        from (irb):23

irb(main):024:0> t.fun
"blah"
"bloo"
=> nil

1. Class variables are these odd things that are shared among every instance of Test.
2. Class variables of Test are not available to class methods of Test itself.
3. The singleton class for Test can have instance variables, but not class variables.*
4. Why didn't the second Test.fun call print "bing"?
5. Is there some way to share data between between a class's instance methods and its class methods?

I'm going to go study the PickAxe2 now, but I figured maybe I could get a quicker answer from some of you. :slight_smile:

Devin
*I'm referring to the anonymous subclass of Class that is the class of the Test constant itself. She sells sea shells by the sea shore.

Ruby isn't Java or C++; in Ruby (like in Smalltalk, I think),
essentially everything is an object, including classes. Class objects
are instances of class Class.

-austin

···

On 7/2/05, Brent W. Hughes <brent.hughes@comcast.net> wrote:

I thought that Test.inc was a class method that could be called without
ever instantiating an object of class Test, and that therefore there
would be no "self". Are you saying that Test is not just a class, but
is also an instance of some other class? I don't understand, but then
I'm just a newbie to Ruby.

--
Austin Ziegler * halostatue@gmail.com
               * Alternate: austin@halostatue.ca

We already have a syntax for instance variables, so that's what you use if you want an instance variable on test. The reason class variables don't work like that is that they would then by tricky to reach fro instance objects of the class and that wouldn't be good at all.

Hope that makes sense.

James Edward Gray II

···

On Jul 2, 2005, at 3:05 PM, Devin Mullins wrote:

OK, now I'm confused. I had thought that class variables were just instance variables of the Test object, but it seems that the case is much weirder than that. (Why?)

Hi.

I thought that Test.inc was a class method that could be called without ever instantiating an object of class Test, and that therefore there would be no "self". Are you saying that Test is not just a class, but is also an instance of some other class?

There is an "internal", if makes it easier to understand, representation
of Test, so @@var is there. Kind of when creating t = Test.new, t points
to @@var on the "internal" class.

This is the way you can add or remove methods to a class already
defined, you change the representation on the "internal" class who
shares your change with all other objects of the same class, and
thinking this way, share that variable also.

Kind of when you write

class Test
    def method_one
       puts "one!"
    end
end
t1 = Test.new

and then, later

class Test
    def method_two
       puts "two"
    end
end
t2 = Test.new

you have BOTH methods on t1 and t2, not matter that t1 was defined
before it was added, you changed that "internal" class where t1 and t2
are using as reference. When you create a class variable, think it is
stored there.

Best regards,

···

----------------------------
Eustáquio "TaQ" Rangel
eustaquiorangel@yahoo.com

Usuário GNU/Linux no. 224050

Hi --

James Edward Gray II wrote:

If you want it to be the same variable in both places, you need a class variable:

class Test
@@var = 0

...

James Edward Gray II

OK, now I'm confused. I had thought that class variables were just instance variables of the Test object, but it seems that the case is much weirder than that. (Why?)

Actually the case is *less* weird than that :slight_smile: It comes down to:
every object can have instance variables (including Class objects),
and class variables are a completely separate matter.

The confusion, I think, arises from the visual similarity (@ and @@),
which suggests that there's some relation between the two. Then
discussion proceeds as to how to reconcile them, or which should
become more like the other, etc. -- which are really solutions in
search of a problem.

This confusion arises a lot. It's perhaps the main reason I would
like to see class variables disappear in 2.0. They make it much
harder for people to understand that classes can have instance
variables, and that in turn interferes with understanding the whole
instance variable concept as well as the "a class is itself an object"
concept.

David

···

On Sun, 3 Jul 2005, Devin Mullins wrote:

--
David A. Black
dblack@wobblini.net

OK, now I'm confused. I had thought that class variables were just
instance variables of the Test object, but it seems that the case
is much weirder than that. (Why?)

We already have a syntax for instance variables, so that's what you
use if you want an instance variable on test. The reason class
variables don't work like that is that they would then by tricky to
reach fro instance objects of the class and that wouldn't be good at
all.

Let me add to that that usually you want to associate a variable with the class instance or with instances. Class variables (the ones with @@) have some strange properties that sometimes lead to surprising behavior. I generally recommend to not use them. Instance variables in classes are much simpler to handle and much clearer and cleaner IMHO.

Just a simple example where each new instance gets assigned a serial number:

class Foo
  @cnt = 0
  def self.tick() @cnt += 1 end

  attr_reader :serial

  def initialize
    @serial = self.class.tick
  end
end

?> instances = (1..10).map { Foo.new }
=> [#<Foo:0x1017e248 @serial=1>, #<Foo:0x1017e1a0 @serial=2>, #<Foo:0x1017e0e0 @serial=3>, #<Foo:0x1017dff0 @serial=4>, #<Foo:0x1017
df60 @serial=5>, #<Foo:0x1017deb8 @serial=6>, #<Foo:0x1017de58 @serial=7>, #<Foo:0x1017ddc8 @serial=8>, #<Foo:0x1017dd50 @serial=9>,
#<Foo:0x1017dca8 @serial=10>]

instances.map {|f| f.serial}

=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Note that this has to be changed slightly if you want to inherit from Foo. I just didn't want to make this overly complicated.

Kind regards

    robert

···

James Edward Gray II <james@grayproductions.net> wrote:

On Jul 2, 2005, at 3:05 PM, Devin Mullins wrote:

Hey Robert!

Let me add to that that usually you want to associate a variable with the class instance or with instances. Class variables (the ones with @@) have some strange properties that sometimes lead to surprising behavior. I generally recommend to not use them. Instance variables in classes are much simpler to handle and much clearer and cleaner IMHO.

Just to make things more clear,

irb(main):001:0> class Test
irb(main):002:1> @@v1 = 0 # class variable?
irb(main):003:1> @v2 = 1 # ???
irb(main):004:1> def initialize
irb(main):005:2> @v3 = 2 # instance variable?
irb(main):006:2> end
irb(main):007:1> def one
irb(main):008:2> @@v1
irb(main):009:2> end
irb(main):010:1> def two
irb(main):011:2> @v2
irb(main):012:2> end
irb(main):013:1> def three
irb(main):014:2> @v3
irb(main):015:2> end
irb(main):016:1> end
=> nil
irb(main):017:0> t = Test.new
=> #<Test:0xb7dc6574 @v3=2>
irb(main):018:0> t.one
=> 0
irb(main):019:0> t.two
=> nil
irb(main):020:0> t.three
=> 2

What is the correct names of v1, v2 and v3? v1 is a class variable, but what about v2 and v3? We can say that v3 belongs to the class instance (we saw that after creating the class v3 is on the output <Test:0xb7dc6574 @v3=2>)on t, but v2 belongs to the class Test?

The answer is the difference to create the variables just after the class statement and before the initialize method OR create it in the initialize method, right?

And v2 is not reached by the two method, but if I change the class and insert

irb(main):026:0> class Test
irb(main):027:1> def self.four
irb(main):028:2> @v2
irb(main):029:2> end
irb(main):030:1> end

and use

irb(main):032:0> t.class.four
=> 1

I can reach it. So where v1 and v2 exactly are named and belongs to? I can see that each t haves it's own v3, but still didn't get the way the or ones are. How v1 and v2 are located on different places.
Kind of

+-------+ +-----+

Test +-----+ t |

+-------+ +-----+

···

@@v1? | | @v3 |
@v2? | +-----+

+-------+

Maybe v1 and v2 are on the same place (the Test instance - v1 needs to be shared by all Test's, right?) but just can be reached on different ways (v2 using four)?

On the pickaxe we have an example

class SongList
   MaxTime = 5*60 # 5 minutes
   def SongList.isTooLong(aSong)
     return aSong.duration > MaxTime
   end
end

On this case, MaxTime resides on the same place that v2 or not? Because if I change SongList and add

class SongList
   def isTooLong(aSong)
     return aSong.duration > MaxTime
   end
end

and use

s = SongList.new
s.isTooLong(<song here>)

I have a valid result, but something like

irb(main):057:0> class SongList2
irb(main):058:1> @maxtime = 5*60
irb(main):059:1> def SongList2.isTooLong(t)
irb(main):060:2> return t > @maxtime
irb(main):061:2> end
irb(main):062:1> def isTooLong(t)
irb(main):063:2> return t > @maxtime
irb(main):064:2> end
irb(main):065:1> end
=> nil
irb(main):066:0> s2 = SongList2.new
=> #<SongList2:0xb7d733d8>
irb(main):067:0> s2.isTooLong(301)
ArgumentError: comparison of Fixnum with nil failed
         from (irb):63:in `>'
         from (irb):63:in `isTooLong'
         from (irb):67
         from (null):0
irb(main):068:0> SongList2.isTooLong(301)
=> true
irb(main):069:0> SongList2.isTooLong(30)
=> false

gives me that error, so there is also a scope difference on a constant like MaxTime and a variable like @maxtime, defined on the class body?

Thanks! :slight_smile:

----------------------------
Eustáquio "TaQ" Rangel
eustaquiorangel@yahoo.com

Usuário GNU/Linux no. 224050

Robert Klemme wrote:

Class variables (the ones with @@) have some strange properties that sometimes lead to surprising behavior.

Indeed. I figured out why my code sample didn't work. Ruby considers it a "toplevel singleton method." If I define a class method inside the class definition, it works, but if I define it outside (as I did in my email), it's looks to the closest class definition outward -- in this case, the thing irb wraps my code in. This is one of those odd cases where irb acts differently from Ruby-raw, too. Also, Ruby didn't warn me about toplevel singleton access like they said it should. I noticed it does, though, if I use class << Test syntax.

This make sense, now. def Test.blah is a singleton method, and Ruby doesn't know anything about class scope when it's looking at this definition, because it's treating Test like any old object on which to define a singleton method. It needs to be stuck inside a class Blah...end block to know where the class variables lie.

Still icky, though. (See below for my RCR-lite.)

I generally recommend to not use them. Instance variables in classes are much simpler to handle and much clearer and cleaner IMHO.

Just a simple example where each new instance gets assigned a serial number:

Thanks for the example. I'm just wondering why

class Foo
  def blah
    @@cnt += 1
  end
end

couldn't have been a shortcut for [an optimization of]:

class Foo
  class << self
    attr_accessor :cnt
  end
  def blah
    self.class.cnt += 1
  end
end

And why instead class variables were done the way they were.

And if I don't get a decent answer, I'll go complain about it in my imaginary blog! So take that, matz!

Devin

Hey Robert!

Let me add to that that usually you want to associate a variable with
the class instance or with instances. Class variables (the ones with
@@) have some strange properties that sometimes lead to surprising
behavior. I generally recommend to not use them. Instance
variables in classes are much simpler to handle and much clearer and
cleaner IMHO.

Just to make things more clear,

I'm not sure about "more clear" with your example... :slight_smile:

irb(main):001:0> class Test
irb(main):002:1> @@v1 = 0 # class variable?
irb(main):003:1> @v2 = 1 # ???
irb(main):004:1> def initialize
irb(main):005:2> @v3 = 2 # instance variable?
irb(main):006:2> end
irb(main):007:1> def one
irb(main):008:2> @@v1
irb(main):009:2> end
irb(main):010:1> def two
irb(main):011:2> @v2
irb(main):012:2> end
irb(main):013:1> def three
irb(main):014:2> @v3
irb(main):015:2> end
irb(main):016:1> end
=> nil
irb(main):017:0> t = Test.new
=> #<Test:0xb7dc6574 @v3=2>
irb(main):018:0> t.one
=> 0
irb(main):019:0> t.two
=> nil
irb(main):020:0> t.three
=> 2

What is the correct names of v1, v2 and v3? v1 is a class variable,
but what about v2 and v3? We can say that v3 belongs to the class
instance (we saw that after creating the class v3 is on the output
<Test:0xb7dc6574 @v3=2>)on t, but v2 belongs to the class Test?

In fact you have v2, v2 and v3 which shows a bit unfortunate naming because these are three different things. They are all instance variables only that the first v2 is an instance variable of the class object while the second v2 is an instance variable of each Test instance. These are not the same nor do they interfere with each other.

The answer is the difference to create the variables just after the
class statement and before the initialize method OR create it in the
initialize method, right?

Yes. And you can create them even later. Instance variables can spring into existing any time (i.e. during any method execution, see also #instance_variable_get, ..set etc). Ruby is different than other OO languages where you usually have to declare variables. In Ruby, you just use them. Whenever you do @something=x then the instance that is currently referred to by self will have an instance variable named "something".

And v2 is not reached by the two method, but if I change the class and
insert

irb(main):026:0> class Test
irb(main):027:1> def self.four
irb(main):028:2> @v2
irb(main):029:2> end
irb(main):030:1> end

and use

irb(main):032:0> t.class.four
=> 1

I can reach it. So where v1 and v2 exactly are named and belongs to? I
can see that each t haves it's own v3, but still didn't get the way
the or ones are. How v1 and v2 are located on different places.
Kind of

+-------+ +-----+

Test +-----+ t |

+-------+ +-----+

@@v1? | | @v3 |
@v2? | +-----+

+-------+

You're missing @v2 in the right object.

Maybe v1 and v2 are on the same place (the Test instance - v1 needs to
be shared by all Test's, right?) but just can be reached on different
ways (v2 using four)?

Yes.

On the pickaxe we have an example

class SongList
   MaxTime = 5*60 # 5 minutes
   def SongList.isTooLong(aSong)
     return aSong.duration > MaxTime
   end
end

On this case, MaxTime resides on the same place that v2 or not?
Because if I change SongList and add

class SongList
   def isTooLong(aSong)
     return aSong.duration > MaxTime
   end
end

and use

s = SongList.new
s.isTooLong(<song here>)

I have a valid result, but something like

irb(main):057:0> class SongList2
irb(main):058:1> @maxtime = 5*60
irb(main):059:1> def SongList2.isTooLong(t)
irb(main):060:2> return t > @maxtime
irb(main):061:2> end
irb(main):062:1> def isTooLong(t)
irb(main):063:2> return t > @maxtime
irb(main):064:2> end
irb(main):065:1> end
=> nil
irb(main):066:0> s2 = SongList2.new
=> #<SongList2:0xb7d733d8>
irb(main):067:0> s2.isTooLong(301)
ArgumentError: comparison of Fixnum with nil failed
         from (irb):63:in `>'
         from (irb):63:in `isTooLong'
         from (irb):67
         from (null):0
irb(main):068:0> SongList2.isTooLong(301)
=> true
irb(main):069:0> SongList2.isTooLong(30)
=> false

gives me that error, so there is also a scope difference on a constant
like MaxTime and a variable like @maxtime, defined on the class body?

The trick is in the lookup: @something always refers to the current instance at the moment of execution. Your instance method isTooLong (which btw. in Ruby convention would be named too_long?) refers to a @maxtime instance variable of the SongList2 instance - as these instances don't have a @maxtime you get nil.

Constants are looked up via in class scope - naturally because you cannot have constances in an instance.

Kind regards

    robert

···

"Eustáquio Rangel de Oliveira Jr." <eustaquiorangel@yahoo.com> wrote:

I agree. Class variables should just be a shortcut for
instance variables of an object's class. Having an independent
and slightly different class variable concept seems redundant,
confusing, and inconsistent.

You could just say that these should be equivalent:

@@x # self.class.instance_eval{@x}
@@x = y # self.class.instance_eval{@x=y}

···

--- Devin Mullins <twifkak@comcast.net> wrote:

Thanks for the example. I'm just wondering why

class Foo
  def blah
    @@cnt += 1
  end
end

couldn't have been a shortcut for [an optimization of]:

class Foo
  class << self
    attr_accessor :cnt
  end
  def blah
    self.class.cnt += 1
  end
end

__________________________________
Discover Yahoo!
Stay in touch with email, IM, photo sharing and more. Check it out!
http://discover.yahoo.com/stayintouch.html

As far as I remember even Matz agrees that class variables are awkward. I think they are on their way out - at least in Ruby 2.

Btw, for extra fun mix inheritance with class variables and change the order in which they are defined between super and sub classes! :slight_smile:

Regards

    robert

···

Devin Mullins <twifkak@comcast.net> wrote:

Robert Klemme wrote:

Class variables (the ones with @@) have some strange properties that
sometimes lead to surprising behavior.

Indeed. I figured out why my code sample didn't work. Ruby considers
it a "toplevel singleton method." If I define a class method inside
the class definition, it works, but if I define it outside (as I did
in my email), it's looks to the closest class definition outward --
in this case, the thing irb wraps my code in. This is one of those
odd cases where irb acts differently from Ruby-raw, too. Also, Ruby
didn't warn me about toplevel singleton access like they said it
should. I noticed it does, though, if I use class << Test syntax.

This make sense, now. def Test.blah is a singleton method, and Ruby
doesn't know anything about class scope when it's looking at this
definition, because it's treating Test like any old object on which to
define a singleton method. It needs to be stuck inside a class
Blah...end block to know where the class variables lie.

Still icky, though. (See below for my RCR-lite.)

I generally recommend to not use them. Instance variables in classes
are much simpler to handle and much clearer and cleaner IMHO.

Just a simple example where each new instance gets assigned a serial
number:

Thanks for the example. I'm just wondering why

class Foo
def blah
   @@cnt += 1
end
end

couldn't have been a shortcut for [an optimization of]:

class Foo
class << self
   attr_accessor :cnt
end
def blah
   self.class.cnt += 1
end
end

And why instead class variables were done the way they were.

And if I don't get a decent answer, I'll go complain about it in my
imaginary blog! So take that, matz!

Devin

Eric Mahurin wrote:

Having an independent
and slightly different class variable concept seems redundant,
confusing, and inconsistent.

And *weird*.

irb(main):001:0> class A
irb(main):002:1> @@n = 0
irb(main):003:1> def initialize
irb(main):004:2> @@n += 1
irb(main):005:2> end
irb(main):006:1> end
=> nil
irb(main):007:0> class B
irb(main):008:1> @@n = 0
irb(main):009:1> def initialize
irb(main):010:2> @@n += 1
irb(main):011:2> end
irb(main):012:1> def A.num
irb(main):013:2> @@n
irb(main):014:2> end
irb(main):015:1> end
=> nil
irb(main):016:0> A.new; B.new; B.new
=> #<B:0x2ac1190>
irb(main):017:0> A.num
=> 2

For extra fun, replace def A.num with def $stdout.num.

You could just say that these should be equivalent:

@@x # self.class.instance_eval{@x}
@@x = y # self.class.instance_eval{@x=y}

Oh, tryin' ta one-up me, eh? Well, that shouldn't be too hard. I'm still learning this stuff. :slight_smile:

Devin

Hey Robert. :slight_smile:

I'm not sure about "more clear" with your example... :slight_smile:

Me neither, to be honest ehehe. :slight_smile:

In fact you have v2, v2 and v3 which shows a bit unfortunate naming because these are three different things. They are all instance variables only that the first v2 is an instance variable of the class object while the second v2 is an instance variable of each Test instance. These are not the same nor do they interfere with each other.

Uhnnn that's because of was declared on the class body and other on the method, right? So to access the first one, only with a class method, right?

Yes. And you can create them even later. Instance variables can spring into existing any time

Not just created on initialize so.
But what is the difference about a @@var class variable and a instance variable of the class? Since @@ at least should be let me say, "unique" (or static perhaps) it's not the same kind of behaviour of a @var defined on the class body? I mean, seems that they are on the same place.

Kind of
+-------+ +-----+

Test +-----+ t |

+-------+ +-----+

>> + |

@@v1? | | @v3 |
@v2? | +-----+

+-------+

You're missing @v2 in the right object.

And the right object for a class body defined @v2 is ... (fill please eheh). :slight_smile:

gives me that error, so there is also a scope difference on a constant
like MaxTime and a variable like @maxtime, defined on the class body?

The trick is in the lookup: @something always refers to the current instance at the moment of execution. Your instance method isTooLong (which btw. in Ruby convention would be named too_long?)

I just copied the Dave Thomas example. :slight_smile:

refers to a @maxtime instance variable of the SongList2 instance - as these instances don't have a @maxtime you get nil.

Mmmm right.

Constants are looked up via in class scope - naturally because you cannot have constances in an instance.

Now I got the constant stuff. :slight_smile:

Thanks!

···

----------------------------
Eustáquio "TaQ" Rangel
eustaquiorangel@yahoo.com

Usuário GNU/Linux no. 224050

Eric Mahurin wrote:

I agree. Class variables should just be a shortcut for
instance variables of an object's class. Having an independent
and slightly different class variable concept seems redundant,
confusing, and inconsistent.

That was confusing me. The way it should be that shortcut, because they
looks like the other a lot.

- ----------------------------
Eustáquio "TaQ" Rangel
eustaquiorangel@yahoo.com

Usuário GNU/Linux no. 224050

As far as I remember even Matz agrees that class variables are awkward.
I think they are on their way out - at least in Ruby 2.

That will lead to a really more clean thing. :slight_smile:
Because @@var and @var (defined on the class body) really looks the same
when you see it at first time.

- ----------------------------
Eustáquio "TaQ" Rangel
eustaquiorangel@yahoo.com

Usuário GNU/Linux no. 224050

Hi --

Thanks for the example. I'm just wondering why

class Foo
  def blah
    @@cnt += 1
  end
end

couldn't have been a shortcut for [an optimization of]:

class Foo
  class << self
    attr_accessor :cnt
  end
  def blah
    self.class.cnt += 1
  end
end

I agree. Class variables should just be a shortcut for
instance variables of an object's class. Having an independent
and slightly different class variable concept seems redundant,
confusing, and inconsistent.

You could just say that these should be equivalent:

@@x # self.class.instance_eval{@x}
@@x = y # self.class.instance_eval{@x=y}

That's a breakage of encapsulation, though. In its capacity as "just
an object", a class should have the same "rights" as any other object
-- specifically, the right to keep its instance variables to itself.

(I understand that no object's instance variables are safe from
instance_eval, but I still wouldn't want to see it hidden behind a
special syntax to the detriment of Class objects.)

I think I like Devin's idea better -- essentially:

   @@x # self.class.x
   @@x = y # self.class.x = y

though I would want the writing of the accessor methods to be explicit
(rather than having the @@x reference cause a singleton method to be
written on the class). This perhaps favors the "a class is just an
object" state of things more than the "classes and their instances
should have a way to share variables" concept, and that in turn
probably reflects my own priorities.

I'm not a big fan of the @@x syntax at all, but to have it work more
smoothly with the whole instance variable system would be much better,
in my view, than having it be a whole separate system which looks
connected to it but isn't.

David

···

On Mon, 4 Jul 2005, Eric Mahurin wrote:

--- Devin Mullins <twifkak@comcast.net> wrote:

--
David A. Black
dblack@wobblini.net

Hi --

>
>> Thanks for the example. I'm just wondering why
>>
>> class Foo
>> def blah
>> @@cnt += 1
>> end
>> end
>>
>> couldn't have been a shortcut for [an optimization of]:
>>
>> class Foo
>> class << self
>> attr_accessor :cnt
>> end
>> def blah
>> self.class.cnt += 1
>> end
>> end
>
> I agree. Class variables should just be a shortcut for
> instance variables of an object's class. Having an
independent
> and slightly different class variable concept seems
redundant,
> confusing, and inconsistent.
>
> You could just say that these should be equivalent:
>
> @@x # self.class.instance_eval{@x}
> @@x = y # self.class.instance_eval{@x=y}

That's a breakage of encapsulation, though. In its capacity
as "just
an object", a class should have the same "rights" as any
other object
-- specifically, the right to keep its instance variables to
itself.

I don't think this is too much different than how it is now -
any instance can directly modify common class variables of its
parent. But, it is another namespace...

I think I like Devin's idea better -- essentially:

   @@x # self.class.x
   @@x = y # self.class.x = y

though I would want the writing of the accessor methods to be
explicit
(rather than having the @@x reference cause a singleton
method to be
written on the class).

I think I like this better too. You could even say
@@superclass to get an easy shortcut to an objects superclass.

Another idea would be to have the parser allow you to call the
"class" method directly rather than have to put the "self." in
there. Or just rename/alias "class" to something else - klass.
   "klass.x" wouldn't be too much longer than "@@x".

···

--- "David A. Black" <dblack@wobblini.net> wrote:

On Mon, 4 Jul 2005, Eric Mahurin wrote:
> --- Devin Mullins <twifkak@comcast.net> wrote:

____________________________________________________
Yahoo! Sports
Rekindle the Rivalries. Sign up for Fantasy Football