【问题标题】:Understanding the arity parameter of the method Proc.curry in Ruby理解Ruby中Proc.curry方法的arity参数
【发布时间】:2019-05-06 08:21:41
【问题描述】:

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

curry -> a_proc

curry(arity) -> a_proc

返回一个柯里化的过程。如果给出了可选的arity 参数,它会确定参数的数量。一个 curried proc 接收一些参数。如果提供了足够数量的参数,它会将提供的参数传递给原始 proc 并返回结果。否则,返回另一个接受其余参数的 curried proc。

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

【问题讨论】:

    标签: ruby currying arity


    【解决方案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" 
    

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

    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 通过为参数提供值给我们连续的Procs,直到我们有足够的能力评估原始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 参数设置了 curried proc 的有效数量;不要费心去看 real arity – p.curry.arity, p.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 具有 n 参数并不意味着您必须使用 n 参数调用它。一个 proc 的 arity 更像是一个建议。

    当然,如果您尝试使用 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
    

    【讨论】:

      猜你喜欢
      • 2014-12-09
      • 2011-05-16
      • 2015-10-06
      • 2012-06-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-02-05
      相关资源
      最近更新 更多