From: Christoph (news_chr) Date: 2004-04-03T00:54:20+09:00 Subject: Re: deciding between ruby and python "Florian Frank" wrote: .... > > this returns a new block that combines the two blocks passed. > > I once played around with this: > > class Proc > > def compose(other) > lambda { |*args| call(*other.call(*args)) } > end My arity preserving solution to this problem was class Proc class << CMP_TABLE = [] def add_comp(n) s = (1..(n < 0 ? 1 - n : n)).collect{|i| "_#{i},"}.join a = n >= 0 ? s.chomp(',') : s << '*_' self << eval("proc {|f,g| proc {|#{s}| f[*g[#{a}].to_a] }}") end (-14..14).each {|n| CMP_TABLE.add_comp(n) } remove_method :add_comp end CMP_TABLE.freeze def *(other) CMP_TABLE[other.arity - 15][self,other] end end These days one might also want to preserve "block lambda-ness" - which depends on a proc (a Proc instance) being formed using the "Proc.new { ... }" or the "proc { ... }" syntax. Which brings up the question on how to test "block lambda-ness" without writing a C-extension? /Christoph