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