了解Ruby中Proc.curry方法的arity参数

时间:2018-12-04 20:26:10

标签: ruby currying arity

https://ruby-doc.org/core-2.5.3/Proc.html#method-i-curry的Ruby Proc.curry方法的文档中,它说:

  

curry-> a_proc

     

curry(arity)-> a_proc

     

返回一个咖喱​​的过程。如果给出了可选的arity参数,则它确定参数的数量。咖喱过程接收一些参数。如果提供了足够数量的参数,它将提供的参数传递给原始proc并返回结果。否则,返回另一个使用其余参数的咖喱过程。

我知道arity表示函数的参数数量。但是,我不太清楚它在这里如何工作。有人可以帮忙解释一下吗?我已经阅读了文档中的示例,但仍然感到困惑。

1 个答案:

答案 0 :(得分:1)

也许通过一个更好的例子可能会有所帮助。让我们从一个简单的过程开始:

p = proc { |a, b, c| "a=#{a.inspect}, b=#{b.inspect}, c=#{c.inspect}" }
p[1,2,3]
# "a=1, b=2, c=3" 

如果我们在不使用curry参数的情况下调用arity,则很清楚发生了什么:

p.curry          # evaluates to a proc
p.curry[1]       # and a different proc
p.curry[1][2]    # another different proc
p.curry[1][2][3] # "a=1, b=2, c=3" 
p.curry[1,2]     # yet another proc, hooray for procs!
p.curry[1,2][3]  # "a=1, b=2, c=3"
p.curry[1,2,3]   # "a=1, b=2, c=3"

因此p.curry通过提供参数值给我们提供了Proc的连续序列,直到我们有足够的能力来评估原始的Proc为止。现在我们开始添加arity值:

p.curry(1)          # some proc
p.curry(1)[]        # some other proc,
p.curry(1)[1]       # "a=1, b=nil, c=nil" 
p.curry(1)[1, 2]    # "a=1, b=2, c=nil" 
p.curry(1)[1, 2, 3] # "a=1, b=2, c=3"

p.curry(2)          # a proc
p.curry(2)[]        # another proc
p.curry(2)[1]       # oh look, a proc, a lovely surprise
p.curry(2)[1][2]    # "a=1, b=2, c=nil" 
p.curry(2)[1, 2]    # "a=1, b=2, c=nil" 
p.curry(2)[1, 2, 3] # "a=1, b=2, c=3" 

arity参数设置了咖喱过程的有效属性;不要担心 real 实物-p.curry.arityp.curry(1).arity,...-因为它将始终是-1(即可变参数)。结果是p.curry(1)有点像

proc { |a| p[a] }.curry # "change" p's arity to 1 then curry

p.curry(2)有点像:

proc { |a, b| p[a, b] }.curry # "change" p's arity to 2 then curry

等请记住,仅因为(非lambda)proc具有Ar n并不意味着您必须使用n自变量来调用它。 proc的友善比其他任何东西更像是一个建议。

当然,如果您尝试用lambda玩弄这种装饰,那么一切都会变本加厉害,因为lambda十分关心它们的友善度:

λ = ->(a, b, c) {  "a=#{a.inspect}, b=#{b.inspect}, c=#{c.inspect}" }

λ[1]             # ArgumentError (wrong number of arguments (given 1, expected 3))
λ.curry[1]       # a lambda-proc
λ.curry[1][2][3] # "a=1, b=2, c=3" 
λ.curry[1][2, 3] # "a=1, b=2, c=3" 

λ.curry(1)       # ArgumentError (wrong number of arguments (given 1, expected 3))
λ.curry(2)       # ArgumentError (wrong number of arguments (given 2, expected 3))
λ.curry(3)       # a lambda-proc that's just like λ.curry