From: "David A. Black" Date: 2005-01-13T07:07:57+09:00 Subject: Re: Duck Typing as Pattern Matching Hi -- On Thu, 13 Jan 2005, itsme213 wrote: >> class C >> def initialize >> @proxy = [] >> end >> >> def method_missing(*args) >> handle(*args) >> end >> >> private >> def handle(*args) >> @proxy.send(*args) >> end >> end >> >> Now do: >> >> c = C.new >> puts c.respond_to?(:[]=) # false >> c[1] = 2 >> puts c[1] # 2 >> >> In spite of the negative response to respond_to?, the object *does* >> know what to do when sent the message []= (and also []). > > Fine. So you have implemented method_missing and respond_to? in mutually > inconsistent ways. I haven't touched respond_to? I'm just showing you a constraint under which it operates. > But then this is possible in any number of other places > in Ruby where sets of methods are expected to be mutually consistent, but > that is up to the programmer. > > You should have done: > class C > ... your other stuff ... > def respond_to?(x) > x == :[] ? true : super > end > end There's no "should have" here, certainly not based on convention: I don't think I've ever seen a case of adding things to respond_to? like that, even in code which makes all sorts of use of method_missing. The whole point of method_missing is that it catches missing methods. You're not expected to enumerate them by name -- in fact, it would be impossible (not to mention a maintenance nightmare!) -- and if the object thinks it responds to them, then they're not missing. What you *can* do is document the code. It is no coincidence, I think, that the person who coined the term "duck typing" and the author of RDoc are one and the same :-) The only thing that should matter is the knowledge that you can do: c[1] = 2 and maybe a somewhat thicker description of what that means in the case of this object. >> But I think the more fundamental problem is qualitative rather than >> quantitative: it's not just that it's hard to insert all the >> information, but that the "information" available is not, in any case, >> really a full profile of the object. That's why I'd rather just take >> objects as they are, and directly query their capabilities >> (information relating to their type) only when there's a specific need >> to do so. > > Pushing that to (an admittedly absurd) extreme, every method would have a > single *args argument. That's the extreme of a different case actually :-) I'm talking about objects and their responses, nothing about which would lead me to the single *args. > No, seriously, I do understand and respect your > viewpoint. But some of your examples justifying it are not quite correct > (like your class C). It's perfectly correct -- a little artificial, perhaps, but not incorrect. It's actually only the tip of the iceberg when it comes to method_missing; all sorts of such things can happen. I think you're reasoning in a bit of a circle: full run-time type description must be possible in Ruby, because any technique that interferes with it is bad programming. I disagree; I think there's a lot of things that dynamic objects can do that escape that kind of description, and there's no reason to dismiss those things out of hand. (Or maybe you just didn't like my code :-) David -- David A. Black dblack@wobblini.net