"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