Hi -- On Sun, 6 Jun 2004, Ara.T.Howard wrote: > On Sat, 5 Jun 2004, David A. Black wrote: > > > I think that could well work in practice, but wouldn't call it duck > > typing. You're not asking it to quack up front; you're checking its > > module ancestry -- which, I hasten to add, may be exactly what you > > want to do, but isn't the same as what a duck typing approach would > > lead you to. > > > > Let me try to flesh this out with a companion example: > > > > class UnHashlikeError < Exception > > end > > > > module Hashlike > > alias :get_by_key :[] > > end > > > > class Hash # probably inadvisable, as Paul Brannan has > > include Hashlike # recently pointed out... > > end > > > > # ... > > > > value = begin > > obj.get_by_key(k) > > rescue NoMethodError > > raise UnHashlikeError, "Object isn't hashlike" > > end > > > > or something like that. The basic idea here is: get your ducks in a > > row, so to speak, by manipulating the object universe so that a > > certain type or subtype of object understands a certain message, then > > at runtime, send that message and branch on the consequences. > > > > > > David > > hmmmm... i see where you are coming from, but actualy disagree. the > way i see it duck typing is really not extremely different from > interfaces. it's basically just saying 'this thing is a duck if it > quacks like a duck'. in sean's case he's asking if an object > > quacks (#[]) > > like (#[] any_object_not_just_indexes) > > a duck (Hash) But if being a Hash instance is really where all this is going, then it's probably just as well to cut to the chase (#is_a?). > in otherwords he is __exactly__ wanting to know if object posses certain > methods with certain signatures (a #[] methods which takes any 'ol object for > instance). this is asking if an object implements an interface - albeit a > small one. in fact duck typing has always struck me as objects implemnting > fine grained (and perhaps dynamic) interfaces. my approach is simply this: > ruby can't tell me this efficiently now, so, iff all objects can be known > before runtime, i'll simply mark them. I don't think the 'is a' of 'is a duck' is the 'is a' of #is_a?, if that makes any sense :-) This is perhaps a wrinkle in the metaphor: the phrase "... then it is a duck" opens the door a bit to saying, "Well, then, if this is an 'is a' question, why not just use #is_a? I think that the 'duck' of "then it is a duck" is actually more of a virtual creature. I sort of translate the phrase in my mind into something like: If you want something that quacks and waddles, and the thing you've got quacks and waddles, then you've got what you want and may proceed. > i don't see this as checking ancestry > because one could have easily done this via some other form of marking: > > class Hash > def is_hashlike?; true; end > end > > class HashLikeA > def is_hashlike?; true; end > ... > end > > class HashLikeB > def is_hashlike?; true; end > ... > end > > etc. > > case obj.respond_to? 'is_hashlike' > when true > when false > end OK... but I think the method approach is more streamlined. The way I've written it above is a bit bulky, but I could slim it down: v = obj.get_by_key(k) rescue raise UnHashlikeError, "Unhashlike" or even just v = obj.get_by_key(k) and let the caller worry about it. I think this is the most direct route to the heart of the matter, which is whether the method is present. Otherwise you're just adding a step -- checking for hashlike-ness -- when you could fold that step into the method call. (I'm still not really happy with any of these solutions, including mine, that depend on modifying Hash.) David -- David A. Black dblack / wobblini.net