Local Instance Methods

Hi All--

I know there are plans to give Ruby private instance variables, but I'm
wondering if there are any plans to provide the corresponding type of
thing for methods, i.e. local instance methods. To clarify, a local
instance method is a method that does not participate in the
inheritance chain and is only callable from within the class it is
defined.

T.

Hi,

···

In message "Re: Local Instance Methods" on Sat, 23 Jul 2005 23:50:57 +0900, "Trans" <transfire@gmail.com> writes:

I know there are plans to give Ruby private instance variables, but I'm
wondering if there are any plans to provide the corresponding type of
thing for methods, i.e. local instance methods. To clarify, a local
instance method is a method that does not participate in the
inheritance chain and is only callable from within the class it is
defined.

The idea has been considered for several times, but I haven't come up
with the "right" syntax and the behavior.

              matz.

In article <1122130106.912486.45730@g49g2000cwa.googlegroups.com>,
transfire@gmail.com says...

I know there are plans to give Ruby private instance variables, but I'm
wondering if there are any plans to provide the corresponding type of
thing for methods, i.e. local instance methods. To clarify, a local
instance method is a method that does not participate in the
inheritance chain and is only callable from within the class it is
defined.

How's that differ from a singleton method, which Ruby does have?

···

--
Jay Levitt |
Wellesley, MA | I feel calm. I feel ready. I can only
Faster: jay at jay dot fm | conclude that's because I don't have a
http://www.jay.fm | full grasp of the situation. - Mark Adler

Trans wrote:

Hi All--

I know there are plans to give Ruby private instance variables, but I'm
wondering if there are any plans to provide the corresponding type of
thing for methods, i.e. local instance methods. To clarify, a local
instance method is a method that does not participate in the
inheritance chain and is only callable from within the class it is
defined.

That's interesting... what's a use case for that?

Devin

Trans a écrit :

Hi All--

I know there are plans to give Ruby private instance variables,

Ruby will have private instance variables? What a good idea! But how
will that work?

but I'm
wondering if there are any plans to provide the corresponding type of
thing for methods, i.e. local instance methods. To clarify, a local
instance method is a method that does not participate in the
inheritance chain and is only callable from within the class it is
defined.

T.

I don't understand. Isn't what the private keyword is for?

···

--
Lionel Thiry

Personal web site: http://users.skynet.be/lthiry/

Devin Mullins ha scritto:

Trans wrote:

Hi All--

I know there are plans to give Ruby private instance variables, but I'm
wondering if there are any plans to provide the corresponding type of
thing for methods, i.e. local instance methods. To clarify, a local
instance method is a method that does not participate in the
inheritance chain and is only callable from within the class it is
defined.

That's interesting... what's a use case for that?

I guess the point would be to avoid breaking something when inheriting, i.e. if you have an helper method named #foo which you don't publish since it's just used internally, a subclass in the need for a method #foo could redefine it and cause breakage of inherited methods that used to rely on the former behaviour.
Thus, everyone subclassing would need to know the internals of evry ancestor class to avoid problems.

I think you can do this via unbinding/rebinding a method but it is ugly.

I'd like for private methods to behave this way.

Hi --

In article <1122130106.912486.45730@g49g2000cwa.googlegroups.com>,
transfire@gmail.com says...

I know there are plans to give Ruby private instance variables, but I'm
wondering if there are any plans to provide the corresponding type of
thing for methods, i.e. local instance methods. To clarify, a local
instance method is a method that does not participate in the
inheritance chain and is only callable from within the class it is
defined.

How's that differ from a singleton method, which Ruby does have?

Say you had:

   class C
     def_local_instance_method x
     # ...
     end
   end

   class D < C
   end

   c = C.new
   c.x
   cc = C.new
   cc.x

   d = D.new
   d.x # No such method

Note that both of my C instances respond to x (it's not a singleton
method on a particular object), but the D instance doesn't.

David

···

On Sun, 24 Jul 2005, Jay Levitt wrote:

--
David A. Black
dblack@wobblini.net

but I'm
wondering if there are any plans to provide the corresponding type of
thing for methods, i.e. local instance methods. To clarify, a local
instance method is a method that does not participate in the
inheritance chain and is only callable from within the class it is
defined.

T.

I don't understand. Isn't what the private keyword is for?

Private in Ruby means that methods declared private may be called only without specifying a receiver. A subclass can call a superclass' private method as long as it is called as method() and not self.method(). Unlike in Java and C++, where "private" means, well, private for instances of this particular class.

Gennady.

···

On Jul 23, 2005, at 15:45, Lionel Thiry wrote:

--
Lionel Thiry

Personal web site: http://users.skynet.be/lthiry/

[...]

wondering if there are any plans to provide the corresponding type of
thing for methods, i.e. local instance methods. To clarify, a local
instance method is a method that does not participate in the
inheritance chain and is only callable from within the class it is
defined.

I don't understand. Isn't what the private keyword is for?

See the example below:

class F
  def f
    b
  end
  private
  def b
    puts "in F#b"
  end
end

f=F.new
f.f # => "in F#b"

class G < F
  # optional
  private
  def b
    puts "in G#b"
  end
end

g=G.new
g.f # => "in G#b", I'd expect "in F#b"

Patrick

Hi --

Trans a écrit :

Hi All--

I know there are plans to give Ruby private instance variables,

Ruby will have private instance variables? What a good idea! But how
will that work?

Based on what Matz has said in the past, there will be a @_ variable
prefix. It's not clear whether @_var will be private, or @var will be
private. Matz has said he wants to use @_var for whichever is used
less often :slight_smile: (Editorial: I actually think that the ugliness of
@_var is enough to make the whole thing questionable, whichever one
it's used for. I'd rather see class variables eliminated, and @@var
used for private instance variables. Then the net amount of
punctuation would stay the same :slight_smile:

Anyway... let's say @_var is private. That means that @_x in a
superclass is different from @_x in a subclass:

   class C
     def set_state(x)
       @_x = x
     end
     def show_state
       puts @_
     end
   end

   class D < C
     def set_hundred
       @_x = 100
     end
     def show_hundred
       puts @_x
     end
   end

Now if you do:

   d = D.new
   d.set_state(1)
   d.set_hundred
   d.show_state # 1
   d.show_hundred # 100

In other words, when you use @_x in class D, you're not using the same
instance variables as @_x in class C. Both "show" methods use @_x,
but they're not the same @_x.

David

···

On Sun, 24 Jul 2005, Lionel Thiry wrote:

--
David A. Black
dblack@wobblini.net

Yukihiro Matsumoto wrote:

The idea has been considered for several times, but I haven't come up
with the "right" syntax and the behavior.

Yes, "right" is the hard part. I suppose we could break down the
possibilities:

1. The mechinism must be either a part of the _call_ or the _def_. An
example of a call mechanism:

  class A
    def f
      A\g # Peter's Syntax
    end
    def g
      "in g"
    end
  end

A possible downside to a call mechinism is that the method is still
part of the inheritance chain. On the upside the syntax can be used to
call specific acestor's methods (i.e. bypassing the direct parent,
which #super dosen't allow).

2. If a _def_ mechinism, then it must either declared or via a syntax
variant. An example of declared:

  class A
    def f
      g
    end
    def g
      "in g"
    end
    local :g
  end

Here's an example of a syntax variant derived from the private instance
vars proposal (eg. @_x):

  class A
    def f
      _g
    end
    def _g
      "in _g"
    end
  end

Are there any other possibilities?

T.

It occurs to me that there is a way to create psuedo-local methods if
we have private instance vars. Assuming instance vars are private:

  class A
    def initialize
      @m = lambda { puts "Like a local method!" }
    end
    def m
      @m.call
    end
  end

That being the case one is led to the possibility of

  def @m
    puts "Like a local method"
  end

T.

gabriele renzi wrote:

I guess the point would be to avoid breaking something when inheriting, i.e. if you have an helper method named #foo which you don't publish since it's just used internally, a subclass in the need for a method #foo could redefine it and cause breakage of inherited methods that used to rely on the former behaviour.
Thus, everyone subclassing would need to know the internals of evry ancestor class to avoid problems.

Ah. Right. Hehe, I program Java* for a living, but couldn't recognize a "private" method from the definition. Silly me.

Thanks,
Devin

*Well, honestly, most of my time programming has been in JSP, since we have a little business-logic-in-the-JSPs problem, and, well, the past few months have been spent largely in introducing CVS and Ant to our little project, so I guess I can be forgiven for forgetting the traditional definition of private, eh?

Gennady Bystritsky a écrit :

but I'm
wondering if there are any plans to provide the corresponding type of
thing for methods, i.e. local instance methods. To clarify, a local
instance method is a method that does not participate in the
inheritance chain and is only callable from within the class it is
defined.

T.

I don't understand. Isn't what the private keyword is for?

Private in Ruby means that methods declared private may be called only
without specifying a receiver. A subclass can call a superclass'
private method as long as it is called as method() and not self.method
(). Unlike in Java and C++, where "private" means, well, private for
instances of this particular class.

Gennady.

Ok, I think I understand. It's a kind of "cheap" private mechanism.
Thanks for the explanation.

···

On Jul 23, 2005, at 15:45, Lionel Thiry wrote:

--
Lionel Thiry

Personal web site: http://users.skynet.be/lthiry/

Hi --

2. If a _def_ mechinism, then it must either declared or via a syntax
variant. An example of declared:

class A
   def f
     g
   end
   def g
     "in g"
   end
   local :g
end

Here's an example of a syntax variant derived from the private instance
vars proposal (eg. @_x):

class A
   def f
     _g
   end
   def _g
     "in _g"
   end
end

Please... no creeping punctuation :slight_smile: I think this concept of local
is clearly in the same group as private/protected/public, and it would
therefore make sense to have it declared.

I'm actually unconvinced of the desireability of it. While it's
reasonable to assume that people may not know every instance variable
that's been used, I think if you're inheriting from a class the burden
is on you to know what that class's instance methods are. It's hard
to imagine a case where it would be otherwise. (Or is there some
other scenario where you would want this?)

David

···

On Sun, 24 Jul 2005, Trans wrote:

--
David A. Black
dblack@wobblini.net

"Trans" <transfire@gmail.com> writes:

An example of a call mechanism:

  class A
    def f
      A\g # Peter's Syntax

I'm not incredibly turned on by that syntax; unfortunately,
I don't have any obviously better suggestion myself.

It would have been nice if we could use the ‘A::g’ syntax
for this. Correct me if I'm wrong, but I think this would
be possible if ‘Curses.addch(?x)’ could *not* be written as
‘Curses::addch(?x)’ (so that ‘Foo::bar’ could be changed to
always mean “invoke ‘bar’ as defined in ‘Foo’ on self”).

(Note that even if this was done, ‘Foo::BAR’ could still
mean what it currently does, because there is no ambiguity
when no method calls are involved.)

While this change would probably break most Ruby code that
currently exists, fixing it could be done mechanically:
Just substitute "\1.\2" for /(\w)::([a-z])/ everywhere.

You'd think another potential option would be ‘self.A::g’,
but of course that currently means ‘self.A.g’, and ‘self.A’
is the only way to call a method named ‘A’. (Though if the
previously mentioned syntax is an option, then so is this.)

    end
    def g
      "in g"
    end
  end

A possible downside to a call mechinism is that the method
is still part of the inheritance chain.

Another downside is that people would be tempted to add the
prefix ‘A\’ to every method call that would have been
non-virtual in C++. I can see two bad consequences of that:

* It would add loads of clutter, including the class name
   sprinkled all over the place.

* It would be a step backwards towards static languages,
   because it would mean tempting people to decide early
   whether or not a method will need to be overridden.

On the upside the syntax can be used to call specific
acestor's methods (i.e. bypassing the direct parent,
which #super dosen't allow).

Yes, that would certainly be useful. I don't think the
syntax is suited for doing “locally private” methods, but
this use case makes it all worthwhile.

I'm thinking primarily about cases such as the following.

  class Foo < Bar
    include Baz
    def initialize(moomin, snufkin)
      super(moomin)
      Baz\initialize(snufkin)
    end
  end

The above could also be written as follows,

  class Foo < Bar
    include Baz
    def initialize(moomin, snufkin)
      Bar\initialize(moomin)
      Baz\initialize(snufkin)
    end
  end

or with the syntax I proposed above:

  class Foo < Bar
    include Baz
    def initialize(moomin, snufkin)
      Bar::initialize(moomin)
      Baz::initialize(snufkin)
    end
  end

If there were a way to make private methods truly private,
that'd be a better approach to “locally private” methods.
But that seems rather difficult to get right.

···

--
Daniel Brockman <daniel@brockman.se>

    So really, we all have to ask ourselves:
    Am I waiting for RMS to do this? --TTN.

That being the case one is led to the possibility of

  def @m
    puts "Like a local method"
  end

+1 Nice reuse of existing symbol that has the same flavor.

Dan

David A. Black wrote:

Hi --

Please... no creeping punctuation :slight_smile: I think this concept of local
is clearly in the same group as private/protected/public, and it would
therefore make sense to have it declared.

I tend to agree.

I'm actually unconvinced of the desireability of it. While it's
reasonable to assume that people may not know every instance variable
that's been used, I think if you're inheriting from a class the burden
is on you to know what that class's instance methods are. It's hard
to imagine a case where it would be otherwise. (Or is there some
other scenario where you would want this?)

I do have a scenario, but in looking at it agian in detail I realize
that only local instance methods as a COMPLETELY SECONDARY NAMESPACE
might be enough to deal with it. Here's the problem: I want to create
an abstraction such that I have no need to be concerned with method
name clashes. The basic example is if I have created a reusable module
A and wish to include it in a subclass of some given class C (Keep in
mind A is created independently and without prior knowledge of C):

  module A
    def f
      "'"
    end
  end

  class C
    def f ; "f" ; end
  end

  class CA < C
    include A
    def f
      f + super
    end
  end

There's a problem b/c A#f is not being called and we get the infinite
loop.

I was thinking that a seperate local method namespace could be used to
solve this, something like:

  class CA < C
    local_include A
    def f
      f + super
    end
  end

So that the methods of module A are included in CA as local and local
methods would have priority, so in this case the call to #f would go to
the right place. To specifically call the public method one would have
to use self.f. But I must confess this has some serious shortcomings,
which makes me think the _call_ mechinism is a much better way to go
--it doen't prevent the inhertiance but maybe that's a good thing, and
as you say the burden is on the inheriter (unlike real life ;-).

T.

I tend to view this as way of minimizing namespace pollution and
possible naming clashes.

What if I want to include two different modules from two different
sources and they both use a common method and/or instance variable
name? How do I resolve that? It isn't enough to rename one of the
methods because internally the module won't be calling the correct
method.

If the name clash is with code I've written I can just use different names
in my code but when merging code from different sources that isn't
necessarily possible without editing the sources.

Private instance methods/vars would not remove this problem but it
would minimize the namespace occupied by a module/class.

Eiffel supports "relative naming" such that when inheriting you
can alter the names of the inherited features to avoid the name
clashes and/or enhance readability. Could Ruby have something like:

     module Helpful
         def update; end
         def private_method;
             do_something
             update
             do_somethingelse
         end
     end

     class A
         include Helpful, {:update => :helpful_update}
         def initialize(target)
             target.add_observer(self)
         end
         def update
             # this is used for the Observer protocol
         end
         def use_helpful
             helpful_update # used for something else
         end
     end

The idea of the hash on include is to change all definitions and
calls of update *within* the module Helpful to be helpful_update
instead. The problem is that I don't think you can do this statically.
You would have to keep track of this information and use it during
method lookup somehow.

Gary Wright

···

On Jul 24, 2005, at 8:37 AM, David A. Black wrote:

I'm actually unconvinced of the desireability of it. While it's
reasonable to assume that people may not know every instance variable
that's been used, I think if you're inheriting from a class the burden
is on you to know what that class's instance methods are. It's hard
to imagine a case where it would be otherwise. (Or is there some
other scenario where you would want this?)

Daniel Brockman wrote:

"Trans" <transfire@gmail.com> writes:

> An example of a call mechanism:
>
> class A
> def f
> A\g # Peter's Syntax

I'm not incredibly turned on by that syntax; unfortunately,
I don't have any obviously better suggestion myself.

That' how I felt at first too, but it grows on you. The other option we
considered was A#g.

It would have been nice if we could use the 'A::g' syntax
for this. Correct me if I'm wrong, but I think this would
be possible if 'Curses.addch(?x)' could *not* be written as
'Curses::addch(?x)' (so that 'Foo::bar' could be changed to
always mean "invoke 'bar' as defined in 'Foo' on self").

(Note that even if this was done, 'Foo::BAR' could still
mean what it currently does, because there is no ambiguity
when no method calls are involved.)

I agree that having '.' and '::' mean the exact same thing is kind of a
waste. But I'm not sure if constants and methods really need a seperate
namespace like they have now.

> A possible downside to a call mechinism is that the method
> is still part of the inheritance chain.

Another downside is that people would be tempted to add the
prefix 'A\' to every method call that would have been
non-virtual in C++. I can see two bad consequences of that:

I don;t think people would be inclided to use extra verbosity unless
they had a strict need to do so. So I don;t think this would be a
serious drawback.

> On the upside the syntax can be used to call specific
> acestor's methods (i.e. bypassing the direct parent,
> which #super dosen't allow).

Yes, that would certainly be useful. I don't think the
syntax is suited for doing "locally private" methods, but
this use case makes it all worthwhile.

True. Well, it provides half of what locally private methods do.

Thanks,
T.