Issue #14541 has been updated by shevegen (Robert A. Heiler).


I'd rather just remove them altogether. :P

However had, since I myself do not use them anyway, it is not really
important to me whether they are there or not - I only use a subset
of ruby which I like. I mostly store stuff that should be available
in a project in the main "namespace", such as module Foobar; end and
using accessors on "Foobar"; and "module-level instance variables"
as I call them, like "module Foobar; @use_colours = true; end".

> Moreover, class variables are extremely complex to implement correctly

Another reason to remove them. ;)

> Is there any library actually taking advantage that class variables
> are inherited between classes? I would guess not or very few.

I think that class variables are not really used that much. I have
not done any analysis but my intuition tells me that most of the
highly used and popular gems available on rubygems.org do not use
them. Again, that is a statement not based on any statistics at all,
but I agree with your comment - I say none of the gems in the top
20 make use of @@variables. I'd even say that IF there were any use,
you could easily write code to NOT require them, too.

> Another option is to remove them completely, but that's likely
> too hard for compatibility.

Oops, I just read your comment here. So you suggest removing too.

I agree with it as well. :)

Compatibility is important but ruby 3.x may make changes to code.
I think matz said so in one of the presentations, so removing
class variables would be a possibility for 3.x.

I do not know whether matz wants to remove them or not. But 
perhaps it could be mentioned in the next ruby developer
meeting.

I think there may be quite many ruby hackers who would not have
any problem if @@class variables would be removed. Since I do
not have any of them in my code, removing class variables would
not impact me at all whatsoever. :)

I think perhaps it would be good to hear:

a) other ruby hackers who used ruby a lot, what they have to say
about @@class variables

and, perhaps even more importantly,

b) anyone who may still, for one reason or the other, use @@class
variables and how easy it may be for them to transition (I guess
it would be very simple because you can do everything without
class variables too, I think, in pure ruby, right? You only need
to be able to catch the event whenever a ruby object is instantiated
and I think that can be done via one of the hooks).


----------------------------------------
Bug #14541: Class variables have broken semantics, let's fix them
https://bugs.ruby-lang.org/issues/14541#change-70594

* Author: Eregon (Benoit Daloze)
* Status: Open
* Priority: Normal
* Assignee: 
* Target version: 
* ruby -v: ruby 2.6.0dev (2018-01-29 trunk 62091) [x86_64-linux]
* Backport: 2.3: UNKNOWN, 2.4: UNKNOWN, 2.5: UNKNOWN
----------------------------------------
Class variables have the weird semantics of being tied to the class hierarchy and being inherited between classes.
I think this is counter-intuitive, dangerous and basically nobody expects this behavior.

To illustrate that, we can break the tmpdir stdlib by defining a top-level class variable:

    $ ruby -rtmpdir -e '$SAFE=1; @@systmpdir=42; p Dir.mktmpdir {}'
    -e:1: warning: class variable access from toplevel
    Traceback (most recent call last):
    	3: from -e:1:in `<main>'
    	2: from /home/eregon/prefix/ruby-trunk/lib/ruby/2.6.0/tmpdir.rb:86:in `mktmpdir'
    	1: from /home/eregon/prefix/ruby-trunk/lib/ruby/2.6.0/tmpdir.rb:125:in `create'
    /home/eregon/prefix/ruby-trunk/lib/ruby/2.6.0/tmpdir.rb:125:in `join': no implicit conversion of Integer into String (TypeError)

Or even simpler in RubyGems:

    $ ruby -e '@@all=42; p Gem.ruby_version'
    -e:1: warning: class variable access from toplevel
    Traceback (most recent call last):
    	3: from -e:1:in `<main>'
    	2: from /home/eregon/prefix/ruby-trunk/lib/ruby/2.6.0/rubygems.rb:984:in `ruby_version'
    	1: from /home/eregon/prefix/ruby-trunk/lib/ruby/2.6.0/rubygems/version.rb:199:in `new'
    /home/eregon/prefix/ruby-trunk/lib/ruby/2.6.0/rubygems/version.rb:199:in `[]': no implicit conversion of String into Integer (TypeError)

So defining a class variable on Object removes class variables in all classes inheriting from Object.
Maybe @@systmpdir is not so prone to conflict, but how about @@identifier, @@context, @@locales, @@sequence, @@all, etc which are class variables of the standard library?

Moreover, class variables are extremely complex to implement correctly and very difficult to optimize due to the complex semantics.
In fact, none of JRuby, TruffleRuby, Rubinius and MRuby implement the "setting a class var on Object removes class vars in subclasses".
It seems all implementations but MRI print :foo twice here (instead of :foo :toplevel for MRI):

~~~ ruby
class Foo
  @@cvar = :foo
  def self.read
    @@cvar
  end
end

p Foo.read
@@cvar = :toplevel
p Foo.read
~~~


Is there any library actually taking advantage that class variables are inherited between classes? I would guess not or very few.
Therefore, I propose to give class variable intuitive semantics: no inheritance, they behave just like variables of that specific class, much like class-level instance variables (but separate for compatibility).

Another option is to remove them completely, but that's likely too hard for compatibility.

Thoughts?



-- 
https://bugs.ruby-lang.org/

Unsubscribe: <mailto:ruby-core-request / ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>