On 1/23/07, SASADA Koichi <ko1 / atdot.net> wrote:
> Hi,
>
> This post is translation of [ruby-dev:30107], a new method dispatch rule
> proposed by Matz.  I post it because I want to discuss about it widely.
>
>
> This change is to clarify "private" feature.
>
> (1) send(:foo) accesses only public methods.
>
> (2) send(:foo) and recv.foo (with receiver method dispatch) only skips
>     private methods.
>     In current Ruby, if any private method foo are there, raise exception.

The combination of 1 and 2 effectively gives private methods a
separate namespace it seems. I'd almost ask to just completely
separate the two with a simple private then public then method_missing
look-up order (see bellow). The main stop for me is how big of a
change this brings.

> (3) method dispatch as function like "foo()", introduce new method
> search ordering.
>
>     1. search *only private methods* in inheritance tree.
>     2. search public methods in inheritance tree from CLASS_OF(self).

I like this a lot. It keeps design focussed. While meta-programming in
Ruby is a big reason to avoid restrictions, the preceding changes make
this one less painful.

The main plus IMO is separating the method_missing calls out from
private look-up. That does leave the question open though, how would
method_missing work at this point? Would there be a good reason to
have separate methods to catch missing private and missing public
calls? Maybe function_missing in line with other names.

> (4) (unconfirmed) private method dispatch searches from caller method class.

This is really interesting as well. I like it in the end because I've
never really bothered to use protected much. it brings back the
meaning to private. It is a big change though and one I would take
with caution. It does discourage the bad styles of monkey patching
that have caused me a lot of pain in the past.

Of course, that does bring up the question of how this changes
protected behavior if at all. I would rather have protected function
more similar to private than public. It is the biggest problem I can
find with rule 4.

> (5) remove send!, __send! methods.  private method funcall is added.
>
>       funcall name, args...

I thought that it was going to originally provide a public interface
to calling. This would probably still work with instance_exec or
similar but somehow I still think public access might be simpler over
all. All assuming I am reading it right...

I can say, however, that I am in favor of the name funcall over send.
While the name is somewhat alien, I think it is something that will
become more familiar over time to rubyists. Considering that the
source of the message is highly restricted, the word method becomes
less meaningful on its own. #funcall seems to fit though I know others
would disagree. I think many underestimate the growing room Ruby has
left for itself.

>
> Japanese developer: please comment if there are any wrong statements or
> lack features.
>

You have done a wonderful job of helping some of us keep up with
ruby-dev in posts like this. Thank you.

>
> I feel C.new.foo returns "C1#m" is strange with following code (because
> of rule 3.1).
>
> class C1
>   def m
>     "C1#m"
>   end
>   private :m
> end
>
> class C2 < C1
>   def m
>     "C2#m"
>   end
>
>   def foo
>     m
>   end
> end

I've got some ideas surrounding the problem I think you are addressing
but I can't quite tell for sure. If you mean C2.new.foo then I would
feel odd about that as well. The look-up order should keep locality as
a primary goal. I think rules like 4 help with that but again, I think
we need some clarification.

In the case that we decide that it must call a private method when no
recv. is given, an idea I had was inheritance of access type from
superclasses with same-name methods. The problem that I see is that
this might incur the overhead of maintaining a complex cache table for
dispatch though I am not yet enough of a dispatch wizard to know if
this is true.

Thanks,
Brian.