如何在ruby中实现curry(部分函数)
发布时间:2020-12-17 03:11:15 所属栏目:百科 来源:网络整理
导读:我需要一些在 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 o
我需要一些在
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,4] #=> [4,3] irb> (curry { |x,*zs| zs << (x+y) })[1][2] #=> [3] irb> (curry { |x,*zs| zs << (x+y) })[1][2,3] irb> (curry { |a,b,c,d,e| a+b+c+d+e })[1,4,5] #=> 15 irb> (curry { |a,e| a+b+c+d+e })[1][2][3][4][5] #=> 15 irb> (curry { |a,2][3][4][5] #=> 15 irb> (curry { |a,e| a+b+c+d+e })[1][2,4][5] #=> 15 我做出了设计决定,让无arg块在currying上返回立即值: irb> curry { 3 } #=> 3 irb> curry { |*xs| xs } #=> [] 这是必要的,以避免每次都用[]结束curry(并且相当像Haskell一样). (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |