From: Eric Mahurin Date: 2005-06-11T00:07:03+09:00 Subject: Re: duck-typing allows deeper polymorphism --- "Ara.T.Howard" wrote: > On Fri, 10 Jun 2005, Eric Mahurin wrote: > > To get maximum benefit from duck-typing, several things > will > > help out: > > > > * For every duck-typed argument, document what the > duck-type is - what > > methods it needs to respond to and what the duck-type > requirements are on > > those method arguments and return values. To help out with > this it would be > > nice if we had something in rdoc for this - but I don't > know what. > > > this shows, right up front in the method, that the method > takes an argument 'x' > which must respond to 'upcase', and 'downcase'. an exception > is thrown if > something that does not respond to both these methods is > passed in: > > harp:~ > cat a.rb > require 'parseargs' > include ParseArgs > > def method(*argv) > pa = parseargs(argv){ > arg :x, :ducktype => %w(upcase downcase) > } > p pa.x.upcase.downcase > end > > method '42' > > harp:~ > ruby a.rb > "42" > > > note that this could be parsed via rdoc quite easily. I don't really like this because: a. if you put this all over the place, it will significantly degrade the code readability b. efficiency. You've added unnecessary checking. Why not let the code raise the exception when it doesn't find the method? c. this may actually hinder some duck typing. In your example above, you might make the method not always call both upcase and downcase (maybe another boolean arg might control that). If the caller has enough control, he could call the method with an object that just responds to one of them. But parseargs unnecessarily prohibit that. d. this only starts to capture the true duck-type. To really describe it, you would need a more elaborate system which included conditions when the arguments methods are called, description of the requirements for the arguments to those methods, and what the duck-type should be for return values of those methods. If you are able to implement that, then you really are going to make the first problem even worse - code clutter. I think the description of the duck-type only belongs in the documentation. I don't really see the advantage of putting it in the code. > > * A convenient way to create objects on-the-fly for > duck-typed > > arguments. Some implementations were given in the thread > > "making a duck". > > two ways exist to do this easily using parseargs: > > * coerce the object into another type > > harp:~ > cat a.rb > require 'parseargs' > include ParseArgs > > def method(*argv) > pa = parseargs(argv){ > ra :x, :ducktype => %w(upcase downcase), 'coerce' => > 'to_s' > } > p pa.x.upcase.downcase > end > > > method 42.0 > harp:~ > ruby a.rb > "42.0" > > > * 'convince' the object that it can behave like a duck by > extending on the fly > > harp:~ > cat a.rb > require 'parseargs' > include ParseArgs > > def method(*argv) > pa = parseargs(argv){ > ra :x, > :ducktype => %w(upcase downcase), > :convince => lambda{|obj| > class << obj > def upcase; '42'; end > def downcase; '42'; end > end > } > } > p pa.x.upcase.downcase > end > > > method Object::new > > harp:~ > ruby a.rb > "42" > > or via a module which should extend the object on the fly for > increased > duck-i-ness: > > harp:~ > cat a.rb > require 'parseargs' > include ParseArgs > > module Ducky > def upcase; '42'; end > def downcase; '42'; end > end > > def method(*argv) > pa = parseargs(argv){ > ra :x, > :ducktype => %w(upcase downcase), > :convince => Ducky > } > p pa.x.upcase.downcase > end > > method Object::new > > harp:~ > ruby a.rb > "42" I'm talking about the caller making the duck, not the method being called. Something like this: # make call act like xyz for this new arg method_where_arg_responds_to_xyz( proc{...}.duck(:xyz,:call) ) > > * Use duck-typing everywhere! > > hear hear! I guess I really should have said "use pure duck-typing everywhere". What I mean by that is that methods shouldn't try to categorize or test the capabilities of their arguments at all - don't use #respond_to?, #class, etc. I used to use #respond_to? occassionally to make overloaded methods, but am now convinced to go the pure duck-typing route - splitting overloaded methods into multiple methods. __________________________________ Discover Yahoo! Have fun online with music videos, cool games, IM and more. Check it out! http://discover.yahoo.com/online.html