On 6/6/05, Eric Mahurin <eric_mahurin / yahoo.com> wrote:
> Regarding duck-typing... Is there an easy way make a "duck"?
> i.e. an object that responds to enough methods to be an
> acceptable argument to a certain methods.  For example, if I
> have a method that takes aString and uses the #size and #[i]
> methods, I could pass it something that looked just enough like
> a String to work:
> 
> alphabet = Object.duck(:[],proc{|i|?a+i},:size,proc{26})
> 
> The implementation I came up with is this:
> 
> class Object
>     def self.duck(*name_proc)
>         duck = self.new
>         duckclass = (class << duck;self;end)
>         while not name_proc.empty?
>             name,proc = name_proc.slice!(0,2)
>             duckclass.send(:define_method,name,&proc)
>         end
>         duck
>     end
> end
> 
> 
> Is there another way to do this?  With all of the talk about
> duck-typing, there would already be something out there to do
> this.

Well, my way isn't really different, and I actually wouldn't use
either "my" way or yours, but in the spirit of ruby I propose this
revision:

  class Object
    def self.duck(methods = {})
      duck = self.new
      duckclass = (class << duck; self; end)
      methods.each do |name,proc|
        duckclass.send(:define_method, name, &proc)
      end
      duck
    end
  end

  alphabet = Object.duck(
    :[] => proc{ |i| ?a+i },
    :size => proc{ 26 }
  )

I simply replaced the array with a hash. Looks a bit cleaner to me.

Jacob Fugal