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

最佳答案

因此,这是使用块而不是方法进行计算的方法:

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

我做出了设计决策,以使no-arg块在curring时立即返回一个值:
irb> curry { 3 }
#=> 3
irb> curry { |*xs| xs }
#=> []

为了避免每次都要以[]结尾(这非常类似于Haskell),这是必要的。

10-06 01:00