Local Instance Methods

T

Trans

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.
 
Y

Yukihiro Matsumoto

Hi,

In message "Re: Local Instance Methods"

|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.
 
J

Jay Levitt

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?
 
D

Devin Mullins

Trans said:
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
 
G

gabriele renzi

Devin Mullins ha scritto:
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.
 
D

David A. Black

Hi --

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
 
D

Devin Mullins

gabriele said:
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?
 
L

Lionel Thiry

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?
 
G

Gennady Bystritsky

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.
 
P

Patrick Gundlach

[...]
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
 
L

Lionel Thiry

Gennady Bystritsky a écrit :
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.
 
D

David A. Black

--927295978-366620376-1122205517=:30414
Content-Type: MULTIPART/MIXED; BOUNDARY="927295978-366620376-1122205517=:30414"

This message is in MIME format. The first part should be readable text,
while the remaining parts are likely unreadable without MIME-aware tools.

--927295978-366620376-1122205517=:30414
Content-Type: TEXT/PLAIN; charset=X-UNKNOWN; format=flowed
Content-Transfer-Encoding: QUOTED-PRINTABLE

Hi --

Trans a =E9crit :

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 :) (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 :)

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 =3D x
end
def show_state
puts @_
end
end

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

Now if you do:

d =3D 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

--=20
David A. Black
(e-mail address removed)
--927295978-366620376-1122205517=:30414--
--927295978-366620376-1122205517=:30414--
 
T

Trans

Yukihiro said:
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.
 
D

David A. Black

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 :) 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
 
T

Trans

David said:
Hi --

Please... no creeping punctuation :) 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.
 
G

gwtmp01

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 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
 
E

Eric Mahurin

--- [email protected] said:
include Helpful, {:update =3D> :helpful_update}

Another way you could accomplish this would be to have a
Module#rename_methods which would return a new module:

include Helpful.rename_methods:)update =3D> :helpful_update)

This along with local methods (maybe just make private methods
local) and local instance variables would help better solve the
multiple inheritance problem.



=09
__________________________________=20
Yahoo! Mail=20
Stay connected, organized, and protected. Take the tour:=20
http://tour.mail.yahoo.com/mailtour.html=20
 
D

David A. Black

Hi --

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 think that any time you do:

def f
f
end

or equivalent, you've decided you want an infinite loop. I don't
think any language design feature that intervenes and "fixes" that for
you would be a good one. (It would make recursion difficult, among
other things.)
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 ;-).

It sounds like you want multiple levels of super, so that you can get
at an arbitrary previously-defined version of a given method (not just
the next one up in the lookup chain). I'm not sure whether this can
be done in an elegant and scaleable way, or whether it's too specific
a use-case for that.


David
 
T

Trans

David said:
I think that any time you do:

def f
f
end

or equivalent, you've decided you want an infinite loop. I don't
think any language design feature that intervenes and "fixes" that for
you would be a good one. (It would make recursion difficult, among
other things.)
Agreed.

It sounds like you want multiple levels of super, so that you can get
at an arbitrary previously-defined version of a given method (not just
the next one up in the lookup chain). I'm not sure whether this can
be done in an elegant and scaleable way, or whether it's too specific
a use-case for that.

Hmm...not so much. I mean that's nice to have I think, but mainly I
just want to encapsulate methods and reuse them elsewhere in such a way
as I don't have to fret so much over name clash. You know, some fine
grain control over interfacing.

T.
 
T

Trans

Eric said:
Another way you could accomplish this would be to have a
Module#rename_methods which would return a new module:

include Helpful.rename_methods:)update => :helpful_update)

I like this, but I imagine it would return an anonymous module. That'll
work but means a large overhead and is unfortunate for marshalling.
Presently I do something similar by creating a named include.

a = named_include Helpful

Then I can call a.update. But this way has it's own shortcomings to.
maybe just make private methods local

I wonder how problematic that would be.

T.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,176
Messages
2,570,949
Members
47,500
Latest member
ArianneJsb

Latest Threads

Top