Rubyでもカリー化

関数型言語ラブな人は、Rubyでもカリー化したくなってくると思います(特にHaskellラブな人はその傾向が強いように思います)。ということで、こんなメソッドを書いてみました。

module Kernel
  def curry(sym, *a1)
    f = sym.respond_to?(:call) ? sym : method(sym)
    lambda do |*a2|
      f.call(*(a1 + a2))
    end
  end
end

使い方はこんな感じです。mapの例を見てください。あぁ何て美しいのでしょう。

def add(a, b)
  a + b
end

p curry(:add, 2)[3]                  # => 5
p curry(method(:add), 2)[3]          # => 5
p curry(lambda {|a, b| a * b}, 2)[3] # => 6

p (1 .. 10).map(&curry(:add, 10))
# => [11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
#
# Haskellで書くとだいたいこんな感じ。
#   main = print $ map (add 10) [1 .. 10]
#       where
#         add a b = a + b

ほとんどのところはふつうのRubyでコードを書いてて、ごく一部分だけピンポイントでカリー化したい場合に使えそうです。Cohi(こひ)でも似たようなことはできるのですが、全面的にRubyぽくなくなってしまうのが難点です。
lambda万歳。lambdaラブ。
参照: http://rubyforge.org/projects/cohi/