"Nathaniel Talbott" <nathaniel / talbott.ws> schrieb im Newsbeitrag 
news:2819AA48-1223-11D9-95A4-000A95CD7A8E / talbott.ws...

> Me too... I haven't found a place to use it since I read about it two 
> minutes ago, but it sends a tingle down my spine just thinking about it. 
> It is definitely polymorphic Ruby goodness. Maybe we can convince Nowake 
> to submit an RCR?

Possible uses are simple adaptors that adapt just one method like these:

1. Condition

ODD = MethodProc(:===) {|x| x % 2 != 0}
....

case n
  when ODD
    ...
  when ...
end


2. Fake Classes

Consider an object pool that needs a class instance as factory (i.e. to 
create new instances).  We can use a MethodProc instead:

class Pool
  def initialize(cl)
    @cl = cl
    @pool = []
  end

  def get() @pool.shift || @cl.new end
  def put(x) @pool << x end
end

pl = Pool.new( MethodProc(:new) { %w{a b c} } )


But the second example shows a more general pattern: what we need here is an 
Adaptor because we might want to check the type of the object returned via 
Class#=== to make sure only proper instances go into the Pool.  In Ruby we 
often use singleton methods to do method adptions, but there might be usages 
where we don't want to change an instance.  Here's a sample implementation:

class Adaptor
  def initialize(obj, mappings)
    @obj = obj
    scl = class<<self; self end

    # delegation of all public methods
    obj.public_methods.each do |m|
      m = m.to_sym

      unless mappings[m]
        scl.class_eval { define_method(m) { |*a| @obj.send(m,*a) } }
      end
    end

    # remapping
    mappings.each do |m,mapped|
      case mapped
        when Symbol
          scl.class_eval { define_method(m) {|*a| @obj.send(mapped,*a) } }
        when Proc
          scl.class_eval { define_method(m,&mapped) }
        else
          raise ArgumentError, "Must be Proc or Symbol"
      end
    end
  end
end

With this we can do

>> sample = %w{aa bb cc}
=> ["aa", "bb", "cc"]
>> fake_class = Adaptor.new(sample, :new => :dup, :=== => :==)
=> ["aa", "bb", "cc"]
>> x = fake_class.new
=> ["aa", "bb", "cc"]
>> "Is an instance of? #{fake_class === x}"
=> "Is an instance of? true"
>> x.id == sample.id
=> false

Now we can modify Pool#put to a more appropriate implementation:

class Pool
  def put(x)
    raise ArgumentError, "illegal type" unless @cl === x
    @pool << x
  end
end

>> pl = Pool.new fake_class
=> #<Pool:0x101b65d8 @cl=["aa", "bb", "cc"], @pool=[]>
>> pl.get
=> ["aa", "bb", "cc"]
>> pl.put( pl.get )
=> [["aa", "bb", "cc"]]
>> pl.put( "foo" )
ArgumentError: illegal type
        from (irb):55:in `put'
        from (irb):62
        from (null):0
>> pl.put( pl.get << "x" )
ArgumentError: illegal type
        from (irb):55:in `put'
        from (irb):63
        from (null):0

I'm not sure though whether there are many applications of this pattern in 
Ruby because we have per instance method definitions with singleton classes. 
What do others think?

Kind regards

    robert