Class variables - a surprising result

My point was that many programmar’s mistake Ruby’s ‘class’ variables as
equivalent to static variables (I did).
Obviously they’re not, but I thought it was worth pointing out that it’s
a source of confusion for some [like myself] (until they learn or are
told otherwise).
The fact that there were several messages about it (and several
mentioning they didn’t know it worked that way [I didn’t for one]) I
think it says something about
its confusing (or perhaps under-documented) nature.

Since you designed the langusge, I’m sure you’re not the slightest bit
confused by it. So, I think you can be discounted when it comes to
tallying the votes on Ruby confusion. :wink:

Cheers…

···

-----Original Message-----
From: Yukihiro Matsumoto [mailto:matz@ruby-lang.org]
Sent: Thursday, August 21, 2003 1:48 PM
To: ruby-talk ML
Subject: Re: Class variables - a surprising result

Hi,

In message “Re: Class variables - a surprising result” on 03/08/22, “Bennett, Patrick” Patrick.Bennett@inin.com writes:

In most languages (C++, Java, Delphi, etc.), class variables (static’s)

are scoped by the class, not the entire inheritance chain.

As far as I know, C++ and Java do not have class variables. They have
static member variables, which can be either private, protected, or
public. I know nothing about Delphi.

						matz.

Hi,

···

In message “Re: Class variables - a surprising result” on 03/08/22, “Bennett, Patrick” Patrick.Bennett@inin.com writes:

Since you designed the langusge, I’m sure you’re not the slightest bit
confused by it. So, I think you can be discounted when it comes to
tallying the votes on Ruby confusion. :wink:

I fell sympathy for your confusion. Unfortunately I can’t satisfy
everyone. I’m trying anyway.

I’d like to know if you are a designer, how would you design class
variables in Ruby? And how useful they are in daily usage?
I’m just curious.

						matz.

Hi,

Since you designed the langusge, I’m sure you’re not the slightest bit
confused by it. So, I think you can be discounted when it comes to
tallying the votes on Ruby confusion. :wink:

I fell sympathy for your confusion. Unfortunately I can’t satisfy
everyone. I’m trying anyway.

I’d like to know if you are a designer, how would you design class
variables in Ruby? And how useful they are in daily usage?
I’m just curious.

  					matz.

Interestingly, I find I never actually use class variables. I don’t know
why or why not. I did in Java, but perhaps Ruby has simpler ways of
achieving the same things?

Gavin

···

In message “Re: Class variables - a surprising result” > on 03/08/22, “Bennett, Patrick” Patrick.Bennett@inin.com writes:

For what it’s worth, what ruby handles these exactly as I
expected they would be handled. Note that I don’t do much
with Java, and I do nothing with C++, so that might be why
ruby’s way of doing it seemed “obviously right” to me.

I do use class variables, but I’ve never wanted one where I
needed a class variable to be different in a subclass than
in the parent class.

···

At 12:15 PM +0900 8/22/03, Yukihiro Matsumoto wrote:

I fell sympathy for your confusion. Unfortunately I can’t
satisfy everyone. I’m trying anyway.

I’d like to know if you are a designer, how would you design
class variables in Ruby? And how useful they are in daily
usage? I’m just curious.


Garance Alistair Drosehn = gad@gilead.netel.rpi.edu
Senior Systems Programmer or gad@freebsd.org
Rensselaer Polytechnic Institute or drosih@rpi.edu

Yukihiro Matsumoto wrote:

I fell sympathy for your confusion. Unfortunately I can’t satisfy
everyone. I’m trying anyway.

Well, keep it up, you’ve done a great job so far. :slight_smile:

I’d like to know if you are a designer, how would you design class
variables in Ruby? And how useful they are in daily usage?
I’m just curious.

Hard to say… Unfortunately the languages I’ve used (some for too
long of a time) tend to cloud my judgement a bit.
I’d probably side more towards the c++ static equivalent where a ‘class’
variable (ie: static int x;) is basically a unique variable that’s within
the namespace of the class but that follows standard visibility rules
during inheritance. If a derived class defines a static (as opposed to
an ‘instance’ variable) then
unless explicitly scoped (class::variable) that class’s variable will be
referenced. If a base class changes its static, only the base class
(and in a way, any subclass that didn’t define a variable with the same
name) are affected.
I guess the real issue is that in Ruby there’s no way to explicitly
‘declare’ a variable. Assigning to it either creates it, or assigns to
the existing instance, so there’s no way for derived classes to declare
their own version of a variable with the same name and be able to
refer to their version or the base class version at will.

Talking through it now, and seeing what what the real source of my
confusion was, I don’t think it’s an issue. Ruby can’t do something I
can do in C++ (guys, please, I don’t want to see a bunch of posts to
simulate this), but honestly, it’s not something you really want to do
anyway. ‘Hiding’ base class variables is usually bad news.
The source of my confusion was that when I saw @@x = y, I equated that
to a static declaration (somewhere) and it being assigned an initial
value, not just another assignment to a variable scoped by a class
hierarchy (as if it was effectively declared in the base class).

If it matters, this is is how I was seeing it all:
class A
@@val = 5
def print
puts “A print - val:#{@@val}”
@@val = 6
end
end

class B < A
@@val = 8
def print
super
puts “B print - val:#{@@val}”
end
end

foo = B.new
foo.print

···

A print - val:8
B print - val:6
A print - val:6
B print - val:6

The equivalent code (at least in terms of how I was looking at it - thus
the source of my confusion) in C++, C#, Delphi (and others) would print
5, 8, 6, 8

> > I'd like to know if you are a designer, how would you design class > > variables in Ruby? And how useful they are in daily usage? > > I'm just curious. > > > > matz. > > Interestingly, I find I never actually use class variables. I don't know > why or why not. I did in Java, but perhaps Ruby has simpler ways of > achieving the same things?

I do regularly. In many classes, I have a SQLIndex which helps me query
values across thousands or more objects quickly. It works like this:

class MyClass
  @_index = SQLIndex.new(...)
end

I also have MyClass._index defined. There was confusion on my part
until I realized that @instance variables in a class were analogous to
"class" or “static” members in Those Other Languages, whereas @@class
variables were different.

Basically, in Ruby, you do have what C++/Java would call a “static
class member”, and you also have something else—@@class variables.
It’s mostly the term here that’s confusing, I think.

···

On Fri, 22 Aug 2003 12:32:12 +0900 “Gavin Sinclair” gsinclair@soyabean.com.au wrote:


Ryan Pavlik rpav@users.sf.net

“Let super-dimensional physics take its course!” - 8BT

Correction to my prior post

‘module05’ and not ‘module4’.

Regards,

Mark

Interesting reading can be found in the ‘module4’ pdf here:

http://wuarchive.wustl.edu/languages/smalltalk/Smalltalk/Squeak/docs/
BHoran/

It discusses Smalltalk’s use of class variables and class instance
variables and provides examples of when one might wish to use them.
Caution is called for in using class variables with a class hierarchy,
because a change in the class variable in the superclass is changed for
all subclasses, so the value represented should be one that should
change in this way in the model.

It also appears that Smalltalks ‘pool dictionaries’ have some
similarities to Ruby modules (although they seem more limited than Ruby
modules).

As a note, unrelated to the issue of class variables and class instance
variables, I thought the book’s initial discussion of inheritance
(having Financial_history be a subclass of Spending_history) represents
what would probably be a poor design decision, on many grounds.

Regards,

Mark

···

On Thursday, August 21, 2003, at 11:41 PM, Ryan Pavlik wrote:

>> I'd like to know if you are a designer, how would you design class >> variables in Ruby? And how useful they are in daily usage? >> I'm just curious. >> >> matz. > > Interestingly, I find I never actually use class variables. I don't > know > why or why not. I did in Java, but perhaps Ruby has simpler ways of > achieving the same things?

I do regularly. In many classes, I have a SQLIndex which helps me
query
values across thousands or more objects quickly. It works like this:

class MyClass
  @_index = SQLIndex.new(...)
end

I also have MyClass._index defined. There was confusion on my part
until I realized that @instance variables in a class were analogous to
“class” or “static” members in Those Other Languages, whereas @@class
variables were different.

Basically, in Ruby, you do have what C++/Java would call a “static
class member”, and you also have something else—@@class variables.
It’s mostly the term here that’s confusing, I think.
[snip]

Ryan Pavlik wrote:

Basically, in Ruby, you do have what C++/Java would call a “static
class member”, and you also have something else—@@class variables.
It’s mostly the term here that’s confusing, I think.

No, @variables are like normal instance variables in C++. They
definitely aren’t like C++ 'static’s.
@@variables aren’t like C++ statics either, but that’s not necessarily a
bad thing - it’s just… different :wink:

Patrick Bennett wrote:

Ryan Pavlik wrote:

Basically, in Ruby, you do have what C++/Java would call a “static
class member”, and you also have something else—@@class variables.
It’s mostly the term here that’s confusing, I think.

No, @variables are like normal instance variables in C++. They
definitely aren’t like C++ 'static’s. @@variables aren’t like C++
statics either, but that’s not necessarily a bad thing - it’s
just… different :wink:

@variables are only like C++ instance variables when used within
instance methods. If you do:

class Foo
@var = 6

def Foo.print
   p @var
end

def print
   p @var
end

end

Then:

Foo.print # => 6
Foo.new.print # => nil

If you want to access these in instance methods, you need to do:

class Foo
def instance_meth
p self.class.class_eval { @var }
end
end

You cannot do:

class Foo
def instance_meth
p class << self; @var; end
end
end

Because @var is an instance variable in the Foo class object, not in the
singleton class object
of an instance of Foo (or maybe there’s some other explanation I can’t
come up with).

So it is effectively a class instance variable, although that’s still
not the same as a Java static
variable, since it’s not inherited.

  • Dan

Ryan Pavlik wrote:

Basically, in Ruby, you do have what C++/Java would call a “static
class member”, and you also have something else—@@class variables.
It’s mostly the term here that’s confusing, I think.

No, @variables are like normal instance variables in C++. They
definitely aren’t like C++ 'static’s.

yet another point of misunderstood, I suppose :slight_smile:

the thing he’s talking about is ‘instance variables of Class objects’,
they are impossible in java cause Class is not an object, but you can
ue them in ruby.

the way to use them has been showed a couple of time by now:

class My
class <<self
attr_accessor :my_var
end
end
=> nil
My.my_var
=> nil
My.my_var=10
=> 10
My.my_var
=> 10

···

il Fri, 22 Aug 2003 13:09:21 +0900, Patrick Bennett patrick.bennett@inin.com ha scritto::

It discusses Smalltalk’s use of class variables and class instance
variables and provides examples of when one might wish to use them.
Caution is called for in using class variables with a class hierarchy,
because a change in the class variable in the superclass is changed for
all subclasses, so the value represented should be one that should
change in this way in the model.

Some notes one that.

VisualWorks used to call them class variables but they are now called
static variables because that’s what people know from C++ or Java.
(The book seems to be about Smalltalk-80 which is the predecessor of
VisualWorks.)

I’ve never had any problems using them because the bytecode compiler
warns if you try to shadow a variable which is already defined in the
superclass. You couldn’t do that with static variables in C++, either.

On the other hand: Smalltalk novices often have problems to understand
what class instance variables are for. I think it’s better to leave
them to advanced programmers. Although they sometimes become useful -
in most cases you won’t miss them. You could probably do several years
of Smalltalk programming without any knowledge about the underlying
meta-model with no harm.

It also appears that Smalltalks ‘pool dictionaries’ have some
similarities to Ruby modules (although they seem more limited than Ruby
modules).

Sorry, but I don’t see any parallels there. Pool dictionaries are a
means to store global or static data (and restrict access to them) but
usually not compiled methods. Compiled methods are part of some class
organisation structure and are only usable if associated to a class or
metaclass. I’ve seen hacks which replaced those associations
dynamically but you wouldn’t call this type of programming “normal”.

Cheers
Sascha

···

Mark Wilson mwilson13@cox.net wrote:

Dan Doel wrote:

@variables are only like C++ instance variables when used within
instance methods. If you do:

class Foo
@var = 6
def Foo.print
p @var
end

def print
p @var
end
end

Then:

Foo.print # => 6
Foo.new.print # => nil

Geesh - sneaky stuff… This kind of thing definitely violates the
P.O.L.S. imo. For one, having the ‘same’ variable actually be two
different ‘instances’ (one, a class variable effectively,
and another, an instance variable) is very confusing. I understand it
now (although I have to think about it for a sec, and personally, I
think that’s a bad sign).
I think the above @var=6 assignment outside of a method decl should be
illegal. It should have to be a @@ reference.

If you want to access these in instance methods, you need to do:

class Foo
def instance_meth
p self.class.class_eval { @var }
end
end

Cool - and interesting, but if I ever saw this in somebody’s code,
well… let’s just say I’d give them a stern look. :wink:

So it is effectively a class instance variable, although that’s still
not the same as a Java static
variable, since it’s not inherited.

Still not the same. :wink:

gabriele renzi wrote:

the thing he’s talking about is ‘instance variables of Class objects’,
they are impossible in java cause Class is not an object, but you can
ue them in ruby.

Also not quite correct. A class in Java is an object. But you can’t
define variables or methods for the class (well you can define static
variables and methods, but they are not really part of the class object,
but you can query them using reflection on the class object).

Regards,

Peter

Patrick Bennett patrick.bennett@inin.com skrev den Fri, 22 Aug 2003
13:59:54 +0900:

Geesh - sneaky stuff… This kind of thing definitely violates the
P.O.L.S. imo. For one, having the ‘same’ variable actually be two
different ‘instances’ (one, a class variable effectively,
and another, an instance variable) is very confusing. I understand it
now (although I have to think about it for a sec, and personally, I think
that’s a bad sign).
I think the above @var=6 assignment outside of a method decl should be
illegal. It should have to be a @@ reference.

I disagree. The class is an instance of the class Class and thus should
be allowed to have instance variables.

/Robert

Dan Doel wrote:

Foo.print # => 6
Foo.new.print # => nil

Geesh - sneaky stuff… This kind of thing definitely violates the
P.O.L.S. imo. For one, having the ‘same’ variable actually be two
different ‘instances’ (one, a class variable effectively,
and another, an instance variable) is very confusing. I understand it
now (although I have to think about it for a sec, and personally, I
think that’s a bad sign).
I think the above @var=6 assignment outside of a method decl should be
illegal. It should have to be a @@ reference.

Definitely not. One of the coolest things about ruby is that when you
say “class” or “module”, it doesn’t open a declarative section of code,
but rather an new executive section. This helps greatly in eliminating
special syntaxes. For instance:

class A
    attr_accessor :a, :b

    private

    def foo; ... end
end

In this case, “attr_accessor” and “private”, which would regularly be
syntax, are actually method calls. This is Very Cool:

class Module
  def def_abstract(*args)
    for sym in args
      module_eval <<-CODE
      def #{sym}(*args); raise SubclassResponsibility; end
      CODE
    end
  end #m:def_abstract
end #c:Module

Now I can do:

class B
   def_abstract :foo, :bar
end

Nifty! In fact, I’ve used this to define new attr_* functions, and a
few other things, to make life easier:

class C
    attr_accessor_typed String, :title, :text
end

The fact that a class or module body is just code along with everything
else gives great flexibility.

As for @instance variables of Class being confusing… it’s not at all.
It’s like this:

#<Class D:0x1234 @a=42>  <--- Over here we have a Class object

   over here we have a D object ----->  #<D:0x4321 @x=0, @y=0>

If you think of everything being an object, the proper place to put your
“static” variables is in the Class object itself. It’s a matter of
understanding the proper way to think about Ruby, rather than trying to
translate it into something else.

···

On Fri, 22 Aug 2003 13:59:54 +0900 Patrick Bennett patrick.bennett@inin.com wrote:


Ryan Pavlik rpav@users.sf.net

“Let super-dimensional physics take its course!” - 8BT

Patrick Bennett wrote:

Geesh - sneaky stuff…

It can get sneakier. There’s more than one way to make a class instance
variable in ruby;
two useful, and two useless.

class Foo
@class_instance_var1 = “I am variable 1”

class << self
   @class_instance_var2 = "I am variable 2"
end

def make3
   class << self
      class << self
         @class_instance_var3a = "I am variable 3a"
      end
      @class_instance_var3b = "I am variable 3b"
   end
end

self.class.class_eval { @class_instance_var4 = "I am variable 4" }

end

Okay:

#1 is an instance variable of the Foo class object. It’s accessed from
instance methods like so:
self.class.class_eval { @class_instance_var1 }
Also, you can use #attr methods to make accessors for you like so:

class Foo
class << self
attr_accessor :class_instance_var1
end
end

#2 is an instance variable of the singleton class of Foo. This is the
type of class instance variable
created when you do:

class << self.class
   ...
end

In an instance method. These are separate from #1 type class instance
variables, so you can’t mix
and match the two. To make an accessor for this, you do:

class Foo
class << self
class << self
attr_accessor :class_instance_var2
end
end
end

#3 has two variables, but they’re equally useless. Essentially they’re
the two different flavors shown
above, but instead of using the Foo class object, you’re using the
singleton class of an instance of
Foo. This essentially makes them no better than instance variables,
unless you capture the singleton
class and make new instances with it, in which case you should be able
to access them using the
methods in #1 and #2.

#4 is the same as #2, except that it uses Foo’s formal class, which is
Class. This makes
@class_instance_var4 available to all classes, which is probably
undesireable.

I’m not sure which of #1 or #2 is more accepted/useful/whatever. There
probably isn’t a concensus,
since I don’t think this comes up a whole lot.

Are we confused yet? :slight_smile:

  • Dan

It would be good if there was a cleaner way to do
this.

This is code that is tackling the language rather than
the problem. One of Ruby’s biggest assets (for me, at
least) is that idioms such as this are so rare.

If this idiom could be replaced with some clear syntax
I think it would be a good thing.

···

If you want to access these in instance methods,
you need to do:

class Foo
def instance_meth
p self.class.class_eval { @var }
end
end

Cool - and interesting, but if I ever saw this in
somebody’s code,
well… let’s just say I’d give them a stern look.
:wink:


Want to chat instantly with your online friends? Get the FREE Yahoo!
Messenger http://uk.messenger.yahoo.com/

That is a really good way to think about it. I think I like the way
that the @@class variables work now.

:o)

-Kurt

···

On Fri, Aug 22, 2003 at 02:19:12PM +0900, Ryan Pavlik wrote:

On Fri, 22 Aug 2003 13:59:54 +0900 > Patrick Bennett patrick.bennett@inin.com wrote:

Dan Doel wrote:

Foo.print # => 6
Foo.new.print # => nil

Geesh - sneaky stuff… This kind of thing definitely violates the
P.O.L.S. imo. For one, having the ‘same’ variable actually be two
different ‘instances’ (one, a class variable effectively,
and another, an instance variable) is very confusing. I understand it
now (although I have to think about it for a sec, and personally, I
think that’s a bad sign).
I think the above @var=6 assignment outside of a method decl should be
illegal. It should have to be a @@ reference.

Definitely not. One of the coolest things about ruby is that when you
say “class” or “module”, it doesn’t open a declarative section of code,
but rather an new executive section. This helps greatly in eliminating
special syntaxes. For instance:

class A
    attr_accessor :a, :b

    private

    def foo; ... end
end

In this case, “attr_accessor” and “private”, which would regularly be
syntax, are actually method calls. This is Very Cool:

class Module
  def def_abstract(*args)
    for sym in args
      module_eval <<-CODE
      def #{sym}(*args); raise SubclassResponsibility; end
      CODE
    end
  end #m:def_abstract
end #c:Module

Now I can do:

class B
   def_abstract :foo, :bar
end

Nifty! In fact, I’ve used this to define new attr_* functions, and a
few other things, to make life easier:

class C
    attr_accessor_typed String, :title, :text
end

The fact that a class or module body is just code along with everything
else gives great flexibility.

As for @instance variables of Class being confusing… it’s not at all.
It’s like this:

#<Class D:0x1234 @a=42>  <--- Over here we have a Class object

   over here we have a D object ----->  #<D:0x4321 @x=0, @y=0>

If you think of everything being an object, the proper place to put your
“static” variables is in the Class object itself. It’s a matter of
understanding the proper way to think about Ruby, rather than trying to
translate it into something else.


Ryan Pavlik rpav@users.sf.net

“Let super-dimensional physics take its course!” - 8BT

======= End of Original Message =======<

Hi –

If you want to access these in instance methods,
you need to do:

class Foo
def instance_meth
p self.class.class_eval { @var }
end
end

Cool - and interesting, but if I ever saw this in
somebody’s code,
well… let’s just say I’d give them a stern look.
:wink:
It would be good if there was a cleaner way to do
this.

This is code that is tackling the language rather than
the problem. One of Ruby’s biggest assets (for me, at
least) is that idioms such as this are so rare.

If this idiom could be replaced with some clear syntax
I think it would be a good thing.

Keep in mind that what’s happening here is, for the sake of
illustration, a kind of prying into another object’s instance
variables that one normally wouldn’t do. So it’s actually OK that
there’s no syntactic sugar for it.

If the object in question (namely, Foo) wants other objects to get at
its instance variables more easily, it will create accessor methods
for them. Then any object (in the right namespace) can say:

Foo.var

substituting for “Foo” anything that evaluates to Foo:

Object.const_get(“Foo”).var
self.class.var # for Foo objects (‘self’ is
# necessary to prevent ‘class’ from
# being read as a keyword)

etc. I’m putting it this way in part to emphasize the fact that
there’s no special relation between an instance of Foo and the
class instance variables of Foo. Foo is an object, and gets to
allow or deny access to its state like any other object.

David

···

On Fri, 22 Aug 2003, [iso-8859-1] Ged Byrne wrote:


David Alan Black
home: dblack@superlink.net
work: blackdav@shu.edu
Web: http://pirate.shu.edu/~blackdav