【问题标题】:Are these two function definitions equivalent?这两个函数定义是否等效?
【发布时间】:2012-09-18 22:50:29
【问题描述】:

我只是在看讲座 2.2 高阶函数(针对 Functional programming principles in Scala)。在那里,一个 sum 函数是这样定义的:

def sum(f: Int => Int, a: Int, b: Int) { ... }

稍后,同样的函数是这样定义的:

def sum(f: Int => Int)(a: Int, b: Int) { ... }

它们似乎是等价的,但没有解释为什么要在上面选择。

【问题讨论】:

  • 另外值得注意的是,当您使用泛型时,泛型类型参数一次绑定一个参数块。所以如果你def f[A](x: A, y: A),那么A将被选择来匹配xy的类型,而def f[A](x: A)(y: A)意味着A的类型将是x的类型,而@ 987654331@ 最好匹配。任何一种行为都可能有用。

标签: scala


【解决方案1】:

第二个定义声明了一个带有两个参数列表的方法。忽略implicits,那么这通常用于启用curried功能应用程序。基本思想是你可以绑定一个函数的一些参数,这会产生另一个带有更少参数的函数,即那些尚未绑定的函数。这是一个简单的教科书示例:

def add(xs: List[Int])(y: Int) =
  xs.map(_ + y)

// Bind first argument and store resulting function in f
val f = add(List(2,3,5,7,11))_

println(f(0))  // List(2, 3, 5, 7, 11)
println(f(10)) // List(12, 13, 15, 17, 21)

// Bind first argument and store resulting function in g
val g = add(List(0,1,0,1,0,1))_

println(g(1))  // List(1, 2, 1, 2, 1, 2)
println(g(-1)) // List(-1, 0, -1, 0, -1, 0)

// Regular invocation
println(add(List(1,2,3))(4)) // List(5, 6, 7)

你会在网上找到很多关于柯里化的文章,例如如何使用currying in Scala,或者有multiple ways to curry in Scala

关于为什么要重新选择一个:在 Haskell 中,您基本上总是会选择 curried 版本而不是 uncurried 版本,因为后者为您提供了能够部分绑定参数的优势,并且没有“语法惩罚”或使用咖喱版本的运行时惩罚。由于这不适用于 Scala(正如您可以从上面的代码 sn-p 中观察到的语法那样),您可能希望更喜欢 uncurried 样式,除非您知道您的方法/函数最可能的用例会benefit from currying

【讨论】:

    【解决方案2】:

    有点,但不完全是。最大的不同在于,拥有多个参数列表可以让我们更轻松地使用函数,而无需指定所有参数。

    例如,让我们像这样定义你的两个函数:

    def sum1(f: Int => Int, a: Int, b: Int) = f(a + b)
    def sum2(f: Int => Int)(a: Int, b: Int) = f(a + b)
    

    现在让我们定义一个函数g,它接受另一个函数作为参数,它接受两个Ints 并产生一个Int

    def g(f: (Int, Int) => Int) = f(3, 5)
    

    具有多个参数列表的sum 版本允许我们只指定第一个列表的参数,然后将这个部分应用的函数传递给g

    g(sum2(_ + 1))
    

    这很简单,也很干净。

    没有单独的参数列表,如sum1,我们必须编写一个lambda表达式来显示ab参数的来源:

    g((a: Int, b: Int) => sum1(_ + 1, a, b))
    

    【讨论】:

      猜你喜欢
      • 2019-10-11
      • 2018-06-02
      • 1970-01-01
      • 2020-11-23
      • 2012-10-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多