Attempted roadmap of future instance variables

Hi –

···

On Fri, 5 Dec 2003, ts wrote:

By the way, I still strongly dislike the @_ form, and would prefer
that all instance vars behave this way than that there be such a
prefix.

Well, for me this is similar to the phrase at the end of the slide 13.

Change the way how work @var actually and you break a big number of
scripts (and I know that if you introduce @_var, you also break some
scripts)

True, but Matz also has emphasized that he’s willing to break a lot of
things at one time (2.0) for the sake of future Ruby. Personally, I’d
be happy to have instance variables stay how they are. My second choice
would be to choose one behavior or the other, avoiding @_ .

David


David A. Black
dblack@wobblini.net

Austin Ziegler wrote:

I rather agree with you on disliking the @_ form, but perhaps
for different reasons. In my module Transaction::Simple, I
have named most of the variables in the pattern @foo
(e.g., @checkpoint) so as to reduce the chance of name
collision. I’m not sure that I want magic behaviour because
of my choice to do this.

The whole point of class local variables is to completely
eliminate the possibility of name collision under subclassing.

/Christoph

What is the problem that @_ variables are trying to solve?

Well, if I remember correctly the original proposition one of the problem
can be summarized with this stupid example.

Imagine that someone define a module which implement a counter, he'll
write something like

   module A
      def increment
         @counter ||= 0
         @counter += 1
      end

      def get
         @counter
      end
   end

because the instance variable @counter is used only to remember some
internal state, this variable is never documented and in the documentation
there is only a reference to #increment and #get

Now someone else use this nice module from RAA and write

   class B
      include A

      def initialize
         @counter = "counter" # he don't know that this variable is used
       end
   end

He has completely broken the module A.

You don't have this problem with class local variable because
  * when you call a method of A : @_counter is a fixnum
  * when you call a method of B : @_counter is a string

Guy Decoux

Wouldn’t it be better just to have instance vars (@foo) local to the class.
Then subclasses and superclasses (and reportedly singletons too) would have
to go through accessor methods? Just seems like a simpler and more elegant
solution. Or is there a problem with this that I’m not seeing (besides “back
breaking” compatability)?

T.

···

On Friday 05 December 2003 05:40 pm, Christoph wrote:

Austin Ziegler wrote:

I rather agree with you on disliking the @_ form, but perhaps
for different reasons. In my module Transaction::Simple, I
have named most of the variables in the pattern @foo
(e.g., @checkpoint) so as to reduce the chance of name
collision. I’m not sure that I want magic behaviour because
of my choice to do this.

The whole point of class local variables is to completely
eliminate the possibility of name collision under subclassing.

so the problem is that there is no concept of ‘private’ instance variables in
ruby. i finally understand - thanks guy.

this is a problem, but i also do not like the @_ syntax. perhaps it would be
preferrable to be able to do this

module A
private @counter
protected @another_var
def increment
@counter ||= 0
@counter += 1
end
def get
@counter
end
end

the default would obviously be public. this would not break existing code.
alternatively, if people prefer symbols we could have

@var # public instance var
_@var # protected instance var
__@var # private instance var

this also would not break exiting (@var) code. maybe it would be too hard to
parse '
@’ and ‘__@’ as atomic token though?

-a

···

On Sat, 6 Dec 2003, ts wrote:

Date: Sat, 6 Dec 2003 01:42:43 +0900
From: ts decoux@moulon.inra.fr
Newsgroups: comp.lang.ruby
Subject: Re: Attempted roadmap of future instance variables…

What is the problem that @_ variables are trying to solve?

Well, if I remember correctly the original proposition one of the problem
can be summarized with this stupid example.

Imagine that someone define a module which implement a counter, he’ll
write something like

module A
def increment
@counter ||= 0
@counter += 1
end

  def get
     @counter
  end

end

because the instance variable @counter is used only to remember some
internal state, this variable is never documented and in the documentation
there is only a reference to #increment and #get

Now someone else use this nice module from RAA and write

class B
include A

  def initialize
     @counter = "counter" # he don't know that this variable is used
   end

end

He has completely broken the module A.

You don’t have this problem with class local variable because

  • when you call a method of A : @_counter is a fixnum
  • when you call a method of B : @_counter is a string

ATTN: please update your address books with address below!

===============================================================================

EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
PHONE :: 303.497.6469
ADDRESS :: E/GC2 325 Broadway, Boulder, CO 80305-3328
STP :: Solar-Terrestrial Physics Data | NCEI
NGDC :: http://www.ngdc.noaa.gov/
NESDIS :: http://www.nesdis.noaa.gov/
NOAA :: http://www.noaa.gov/
US DOC :: http://www.commerce.gov/

The difference between art and science is that science is what we
understand well enough to explain to a computer.
Art is everything else.
– Donald Knuth, “Discover”

/bin/sh -c ‘for l in ruby perl;do $l -e “print "\x3a\x2d\x29\x0a"”;done’
===============================================================================

That’s fine for subclassing, but what about mix-ins?

class A
def initialise
@checkpoint = True
end
end

A.new.extend(Transaction::Simple)

We have a name collision there. Granted, the collision is there today, but I
don’t see how @_ will actually help in the case of mixins.

-austin

···

On Sat, 6 Dec 2003 01:40:42 +0900, Christoph wrote:

Austin Ziegler wrote:

I rather agree with you on disliking the @_ form, but perhaps for
different reasons. In my module Transaction::Simple, I have named most
of the variables in the pattern @foo (e.g., @checkpoint) so as
to reduce the chance of name collision. I’m not sure that I want magic
behaviour because of my choice to do this.
The whole point of class local variables is to completely eliminate the
possibility of name collision under subclassing.


austin ziegler * austin@halostatue.ca * Toronto, ON, Canada
software designer * pragmatic programmer * 2003.12.05
* 12.35.00

This may be crazy (and stupid), but could the syntax be

_@var

instead of

@_var

···

On Friday, 5 December 2003 at 23:15:46 +0900, David A. Black wrote:

Hi –

On Fri, 5 Dec 2003, ts wrote:

Change the way how work @var actually and you break a big number of
scripts (and I know that if you introduce @_var, you also break some
scripts)

True, but Matz also has emphasized that he’s willing to break a lot of
things at one time (2.0) for the sake of future Ruby. Personally, I’d
be happy to have instance variables stay how they are. My second choice
would be to choose one behavior or the other, avoiding @_ .


Jim Freeze

New systems generate new problems.

solution. Or is there a problem with this that I'm not seeing (besides "back
breaking" compatability)?

  ruby -rfileutils -e 'FileUtils.rm_rf("RAA")'

and all scripts used privatively

Guy Decoux

  private @counter
  protected @another_var

You think in C++ :-))

Guy Decoux

Hi,

···

In message “Re: Attempted roadmap of future instance variables…” on 03/12/06, “T. Onoma” transami@runbox.com writes:

Wouldn’t it be better just to have instance vars (@foo) local to the class.
Then subclasses and superclasses (and reportedly singletons too) would have
to go through accessor methods? Just seems like a simpler and more elegant
solution. Or is there a problem with this that I’m not seeing (besides “back
breaking” compatability)?

That would be interesting alternative idea. I think it’s matter of
how much compatibility we would preserve.

						matz.

That's fine for subclassing, but what about mix-ins?

@_var is valid also with module (i.e. mix-ins), not only class

   module A
      def initialize
         @_var = 12
      end

      def get
         p "A : #{@_var}"
      end
   end

   class B
      include A

      def initialize
         @_var = 24
         super
      end

      def get
         p "B : #{@_var}"
         super
      end
   end

   B.new.get # B : 24
             # A : 12

Guy Decoux

I need clarification on this. Using extend doesn’t add a mix-in, but rather a
singleton. Right? I’m not debunking austin’s point or anything, I just need
to be clear on this b/c I’ve seen it refered to as a mix-in before and I
don’t think that’s percise. So I just want to make sure.

Thanks,
T.

···

On Friday 05 December 2003 06:41 pm, Austin Ziegler wrote:

That’s fine for subclassing, but what about mix-ins?

class A
def initialise
@checkpoint = True
end
end

A.new.extend(Transaction::Simple)

I knew I should have read Guy’s response before replying … :slight_smile:

As I understand it, then, because I have chosen @checkpoint as the
variable name, Ruby will implicitly do the right thing, right? Basically,
the
@_ form (class instance local) would look something like:

module B
def frob
@_foo = “B:foo:frob”
end
end

class A
include B

def initialize
  @_foo = "A:foo"
end
def foo
  @_foo
end

end

x = A.new # => <#23251324: A @_foo = “A:foo”>
x.foo # => “A:foo”
x.frob # => “B:foo:frob”
x.foo # => “A:foo”

@_foo is implicitly treated as @_foo(A) or @_foo(B) depending on which
method
was called, right? How would this be shown in #inspect?

<#234251234: A @_foo:A = “A:foo”, @_foo:B = “B:foo:frob”>

I’m not sure I like the @_ form in any case; it feels too “magic” in a way
that “@” and “@@” don’t. I think that I’m getting the way that it works,
though. I also agree with Guy that this magnitude of a change for Ruby2
would
break (IMO) too much if it were applied to all instance variables.

-austin

···

On Sat, 6 Dec 2003 02:41:13 +0900, Austin Ziegler wrote:

On Sat, 6 Dec 2003 01:40:42 +0900, Christoph wrote:

Austin Ziegler wrote:

I rather agree with you on disliking the @_ form, but perhaps for
different reasons. In my module Transaction::Simple, I have named
most of the variables in the pattern @foo (e.g., @checkpoint)
so as to reduce the chance of name collision. I’m not sure that I
want magic behaviour because of my choice to do this.
The whole point of class local variables is to completely eliminate the
possibility of name collision under subclassing.
That’s fine for subclassing, but what about mix-ins?


austin ziegler * austin@halostatue.ca * Toronto, ON, Canada
software designer * pragmatic programmer * 2003.12.05
* 12.45.26

I certainly would prefer that, as I said in [ruby-talk:87290].

David

···

On Sat, 6 Dec 2003, T. Onoma wrote:

On Friday 05 December 2003 05:40 pm, Christoph wrote:

Wouldn’t it be better just to have instance vars (@foo) local to the class.


David A. Black
dblack@wobblini.net

It is a mix-in.

class A; end
class B; include Transaction::Simple; end
x = A.new
y = B.new
x.extend(Transaction::Simple)
class << x; self; end.ancestors
=> [Transaction::Simple, A, Object, Kernel]
class << y; self; end.ancestors
=> [B, Transaction::Simple, Object, Kernel]

It’s just that #extend mixes into the object’s singleton class.

-austin

···

On Sat, 6 Dec 2003 02:50:19 +0900, T. Onoma wrote:

On Friday 05 December 2003 06:41 pm, Austin Ziegler wrote:

That’s fine for subclassing, but what about mix-ins?
class A
def initialise
@checkpoint = True
end
end
A.new.extend(Transaction::Simple)
I need clarification on this. Using extend doesn’t add a mix-in, but
rather a singleton. Right? I’m not debunking austin’s point or anything,
I just need to be clear on this b/c I’ve seen it refered to as a mix-in
before and I don’t think that’s percise. So I just want to make sure.


austin ziegler * austin@halostatue.ca * Toronto, ON, Canada
software designer * pragmatic programmer * 2003.12.05
* 12.58.42

Yukihiro Matsumoto wrote:

That would be interesting alternative idea. I think it’s
matter of how much compatibility we would preserve.

That is obviously your call to make. Personally I sort of prefer
Tom’s solution (it is David’s second choice if I remember
correctly).
However if we would go that route I definitely would throw
out singleton class localness (that puts me somewhere
between Tom and David:-) since having to write (non singleton)
accessors to manipulate instance variables defined in the
(non singleton) super-class (or in the case of special case of
meta classes the “meta super class”) is fairly unappealing to
me.

/Christoph

The core of the problem that class local instance variables are trying
to solve is variable shadowing (as Guy so elegantly showed). The
problem with making all variables class local and using accessors, is
that if I am shadowing an instance variable, there is a good chance
that I will shadow the accessor as well. The superclass variable thus
becomes completely inaccessible:

pretend all instance variables are class local

class A
attr_accessor :a

 def initialize
   @a = 1
 end

end

class B < A
attr_accessor :a

 def initialize
   @a = 'a'
 end

end

There is no way for the subclass to access the superclass’s instance
variable @a now, and I don’t see a good work-around for this.

Personally I don’t like any proposal I’ve seen for this concept yet
(including Matz’). I understand that sometimes there are name clashes
when we’d rather there not be, but every cure I’ve seen seems to be
much worse than the disease, cutting down on the flexibility one
currently has in Ruby to easily access anything that one needs to get
the job done. Yes, as things stand now, it is possible to shoot oneself
in the foot, but there are plenty of other ways to do that, and I don’t
think we’re going to remove all of them in Ruby 2.0. I just know that
I’m going to subclass a framework class in Ruby someday and find that
the one variable that I need to change the value of is a class local
instance variable, and I can’t get access to it. Gives me Java
flashbacks.

I wonder if a better solution for the issue doesn’t lie in the idea of
namespaces. Basically, library writers want to be able to say that
@checkpoint is part of the Transaction::Simple namespace, and
occasionally library users want to say that they want to read or write
@checkpoint in the Transaction::Simple namespace. If there was a way to
explicitly limit the namespace of an instance variable to a given Class
or Module, and a way to access an instance variable in an explicit
Class or Module, that would be quite handy. The key is that all data
remains accessible all the time, to everyone. We just allow folks the
ability to shadow.

Stupid, off the top of my head, code example:

module Transaction::Simple
def initialize
namespace self do
@checkpoint = true
end
end
end

class MyClass
include Transaction::Simple

 def initialize
   @checkpoint = true
   namespace Transaction::Simple do
     @checkpoint = false
   end
 end

end

This is definitely half-baked, but perhaps it will trigger something in
someone’s (read Matz’ :slight_smile: brain.

Nathaniel

<:((><

···

On Dec 5, 2003, at 12:15, Yukihiro Matsumoto wrote:

Hi,

In message “Re: Attempted roadmap of future instance variables…” > on 03/12/06, “T. Onoma” transami@runbox.com writes:

Wouldn’t it be better just to have instance vars (@foo) local to the
class.
Then subclasses and superclasses (and reportedly singletons too)
would have
to go through accessor methods? Just seems like a simpler and more
elegant
solution. Or is there a problem with this that I’m not seeing
(besides “back
breaking” compatability)?

That would be interesting alternative idea. I think it’s matter of
how much compatibility we would preserve.

well, maybe he does :slight_smile:
btw, having something like

make_class_local :var

would be better to me than having another name/scoping rule.
The point to me is: a problem does exists. But the answer is ugly[1].
I’m stupid, so I hope someone else could point out a better one[2] :slight_smile:

[1] actually, ugly for me, but it seem some other people agree… and I
believe even matz look at this new notation as a black sheep :stuck_out_tongue_winking_eye:

[2] I remember this has been debated for long time. But now that the
deadline is approaching someone could squeeze his brain to get a
better solution :slight_smile:

···

il Sat, 6 Dec 2003 02:14:56 +0900, ts decoux@moulon.inra.fr ha scritto::

private @counter
protected @another_var

You think in C++ :-))

A word of update on this idea. I have been writing my lastest code as if this
were already fact, in order to get a realistic feel for what it would be
like. It works fine except for one signifficant age old problem: the
ambiguity between methods and local variables. Because instance variables
would be local to their class, one would then uses writer methods from mixins
and subclasses and so forth. Unfortunately you always have to use self as a
reciever on these to prevent them from being local variables. The age old
ambigutiy rears its head again. Quick ex-

class K
attr_writer :h
end
class Q < K
def hi(x)
self.h = “Hello, #{x}” # must use self
end
end

Honestly, I would prefer using % for local variables and kill this ambiguity
once and for all!

T.

···
on 03/12/06, "T. Onoma" <transami@runbox.com> writes:

Wouldn’t it be better just to have instance vars (@foo) local to the
class. Then subclasses and superclasses (and reportedly singletons too)
would have to go through accessor methods? Just seems like a simpler and
more elegant solution. Or is there a problem with this that I’m not
seeing (besides “back breaking” compatability)?

That would be interesting alternative idea. I think it’s matter of
how much compatibility we would preserve.

Hi –

Yukihiro Matsumoto wrote:

That would be interesting alternative idea. I think it’s
matter of how much compatibility we would preserve.

That is obviously your call to make. Personally I sort of prefer
Tom’s solution (it is David’s second choice if I remember
correctly).

Tied for second with doing nothing :slight_smile:

However if we would go that route I definitely would throw
out singleton class localness (that puts me somewhere
between Tom and David:-) since having to write (non singleton)
accessors to manipulate instance variables defined in the
(non singleton) super-class (or in the case of special case of
^^^

Is this second ‘non’ perhaps not supposed to be there? If it is
supposed to be there, then can you give a couple of examples to
clarify what you mean? :slight_smile:

meta classes the “meta super class”) is fairly unappealing to
me.

David

···

On Sat, 6 Dec 2003, Christoph wrote:


David A. Black
dblack@wobblini.net