The second possibility would be to give methods implemented through method_missing precedence over private methods. Thus without receiver, first a public method is sought for, if not found method_missing is called, if that fails, the private method is called if present. So essentially it tries the call with receiver, then it tries without.
I'm not sure I follow this. If you call a method without receiver, it
would call it *with* receiver first? Or do you mean "with[out]
receiver" behavior would be redefined?
First off, I have to mention that I meant with[out] _explicit_ receiver, of course. Every method call has a receiver.
The idea was that when a method is called without explicit receiver, it is first tried as if it had self as an explicit receiver, and if that fails, the private method is called, if there is one. This makes sure that if the call with explicit receiver succeeds, the call without explicit receiver succeeds in exactly the same way. If the one with fails, the one without can still succeed if there is a private method. It makes sure the capabilities of method calls without explicit receiver are a superset of the ones with explicit receiver. So yes, the "without receiver" behavior would be redefined, the "with receiver" behavior stays the same. In my first option (no method_missing for private methods), it is the other way around.
I think it's still OK to have two versions of Kernel#send, one that does the call as if with receiver, one as if without receiver (which can call private methods) -- however you name them. But the confusion is not because of Kernel#send; it's because of the semantics of method calls with receiver vs without receiver, and changing Kernel#send does not solve that. Well, IMHO at least.
It's also true that "send" implies "receive"... so it doesn't really
mean there isn't a receiver. I think I have to let this percolate a
little before I go on
Does it help if you replace "with[out] receiver" by "with[out] explicit receiver"? When using Kernel#send (as it is now), it is as if you call the method without explicit receiver, hence the ability to call private methods. Actually in a way it is logical that Kernel#send can call private methods, because once execution is in send, self has changed and the method can be called without explicit receiver, enabling calls to private methods. Say I'd define my own send like this:
class Object
def my_send(m, *args, &blk)
eval "#{m}(*args, &blk)"
end
end
class A
def m
1
end
private :m
end
A.new.m # => NoMethodError: private method `m' called for #<A:0x402d67b4>
A.new.my_send(:m) # => 1
Sorry, I have a knack for forgetting to say the obvious things (obvious for me). Well, for all I know, I may have done it again
PS: fcall is used in Ruby's internals to refer to a call without receiver. This looks like a call to a procedural function, hence fcall.
It does? I'm still not thrilled with fcall. It seems strange to
me to introduce the concept of a "function" in Ruby just for this one
purpose.
Of course, same here; it was only meant as clarification. I don't like fcall myself, though I'm not sure about send! either. Matz is introducing send! because send as it is now is confusing, it violates POLS (I think that is appropriate now as I suspect Matz was surprised by send's behavior). And violating POLS is not the same as being dangerous. Of course calling private methods could be dangerous. So I think I can understand Matz's hesitation here.
Peter
···
On Mon, 29 Aug 2005, David A. Black wrote: