This is a late response to the very long thread that started back in
January with this message:
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/9996
As I understand it, the problem Matz is seeking to address is that
private methods are inherited by and may be overridden by subclasses.
This means that a subclass writer can inadvertently alter the behavior
of its superclass simply by defining a method that has the same name as
an internal helper method of the superclass. The only way to defend
against this is for subclass writers to be familiar with the internal
implementation of the superclass.
Matz's proposal was to resolve this problem by altering the method
resolution algorithm. If I understand correctly, the problems were:
1) It was kind of complicated
2) The method lookup algorithm depended on whether a method was called
functionally without an object prefix or in OO form with an object
prefix. (That is called as foo() or o.foo())
3) There were backward compatibility issues
Part of the discussion was about the question of whether to alter the
semantics of private methods, or add a new "local" or "personal"
visibility level for methods that were truely local to the defining
class and could not be inherited or overridden.
With all that as review, here are my thoughts on the matter.
1) It is reasonable to expect private methods (or local methods if we
call them that) to be looked up and dispatched differently than
non-private methods.
2) The problem, though, is that since Ruby is a dynamic language, the
interpreter can't tell whether a method is private or not until it has
looked it up.
3) Therefore, solutions like Matz's proposal depend on the method
invocation syntax (functional style versus object-oriented style) to
determine which method lookup algorithm is to be used. This leads to
the confusing and hard-to-justify situation in which the invocation
"foo" might do something different than the invocation "self.foo".
I propose, therefore, that some new syntax be introduced (avoiding
backward incompatibility) either for making local method names obviously
different from other method names. Or that a new method invocation
syntax be introduced and that this new syntax be used when we want to
invoke a local method defined in (or inherited by) the caller without
considering any methods defined further down the class hierarchy.
I don't grok parse.y well enough to know whether any syntax I would
propose would actually result in an unambiguous grammar, but my
suggestion is that local methods have an @ prefix just like instance
variables do. Then the interpreter knows from the name of the method
that it is to be dispatched differently.
In fact, I might actually go further than this and propose that local
methods are not actually methods, but are syntactic sugar for lambdas.
In Ruby 1.8, we can write code like this:
class Test
def initialize(greeting)
@greeting = greeting
@greeter = lambda { |x| puts "#@greeting #{x}" }
end
def greet(x)
@greeter[x]
end
end
t = Test.new("hello")
t.greet("world")
In this code, the instance variable @greeter refers to a local function
that is completely hidden from subclasses and cannot be altered.
Perhaps Ruby 1.9 could take this idiom and add syntax sugar to make the
definition and invocation of local functions more like the definition
and invocation of regular methods.
David Flanagan