加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

如何在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一样).

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读