如何在 ruby 中实现咖喱(部分功能) [英] how to implement curry(partial function) in ruby
本文介绍了如何在 ruby 中实现咖喱(部分功能)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
我需要一些在 ruby 中实现 curry 函数的示例(1.8.6 或 1.8.7 而不是 1.9).
I need some examples of implementing curry function in ruby(1.8.6 or 1.8.7 not 1.9).
推荐答案
这里是如何用块而不是方法进行柯里化:
So here's how to do currying with blocks, rather than methods:
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
而且它在实践中效果很好.参数可以柯里化或不柯里化,并且像往常一样收集额外的参数:
And it works fairly well in practice. Arguments can be curried or not, and extra arguments are collected as usual:
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
我的设计决定是让无参数块在柯里化时返回一个立即值:
I made the design decision to have no-arg blocks return an immediate value on currying:
irb> curry { 3 }
#=> 3
irb> curry { |*xs| xs }
#=> []
这是必要的,以避免每次都必须以 []
结束柯里化(并且非常类似于 Haskell).
This is necessary to avoid having to end currying with a []
every time (and is fairly Haskell-like).
这篇关于如何在 ruby 中实现咖喱(部分功能)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文