如何在ruby中实现curry(部分函数)

我需要一些在ruby中实现curry函数的例子(1.8.6或1.8.7而不是1.9)。

所以这里是如何用块而不是方法进行currying:

def curry(&block) arity = (block.arity >= 0) ? block.arity : -(block.arity + 1) # return an immediate value if the block has one return block[] if arity == 0 # otherwise, curry it argument by argument args = [] innermost = lambda do |last,*extra| args[arity-1] = last block[*(args+extra)] end (0...(arity-1)).to_a.reverse.inject(innermost) do |inner,i| lambda do |arg_i,*extra| args[i] = arg_i # pass extra arguments on to inner calls if extra.empty? inner else inner[*extra] end end end end 

它在实践中运作得相当好。 参数可以是否为咖喱,并且像往常一样收集额外的参数:

 irb> (curry { |x,y| x + y })[1,2] #=> 3 irb> (curry { |x,y| x + y })[1][2] #=> 3 irb> (curry { |x,*ys| ys << x })[1] #=> [1] irb> (curry { |x,*ys| ys << x })[1,2,3] #=> [2, 3, 1] irb> (curry { |x,y,*zs| zs << (x+y) })[1,2] #=> [3] irb> (curry { |x,y,*zs| zs << (x+y) })[1,2,4] #=> [4, 3] irb> (curry { |x,y,*zs| zs << (x+y) })[1][2] #=> [3] irb> (curry { |x,y,*zs| zs << (x+y) })[1][2,4] #=> [4, 3] irb> (curry { |a,b,c,d,e| a+b+c+d+e })[1,2,3,4,5] #=> 15 irb> (curry { |a,b,c,d,e| a+b+c+d+e })[1][2][3][4][5] #=> 15 irb> (curry { |a,b,c,d,e| a+b+c+d+e })[1,2][3][4][5] #=> 15 irb> (curry { |a,b,c,d,e| a+b+c+d+e })[1][2,3,4][5] #=> 15 

我做出了设计决定,让无参数块在currying上返回立即值:

 irb> curry { 3 } #=> 3 irb> curry { |*xs| xs } #=> [] 

这是必要的,以避免每次都用[]结束currying(并且相当像Haskell一样)。