【问题标题】:What's the rationale behind curried functions in Scala?Scala 中的柯里化函数背后的基本原理是什么?
【发布时间】:2012-09-28 07:40:38
【问题描述】:

我刚接触 Scala,我似乎有点困惑为什么 Scala 提供“咖喱函数”,例如:

//curried function
def add(lhs: Int)(rhs: Int) = lhs + rhs
//so we can do partially binding like
val add1 = add(1)_

这很令人困惑,因为 Scala 已经为普通函数提供了“部分应用程序”,例如,

//normal function
def add(lhs: Int, rhs: Int) = lhs + rhs
//also supports partially application
val add1 = add(1, _: Int) 

所以我的问题是:除了部分应用之外,在 Scala 中使用柯里化函数而不是普通函数还有其他意义吗?

EDT1:感谢您的回复。我想我从以下所有答案中学到了新东西。

【问题讨论】:

  • 这个问题和所有答案实际上是指Scala对多个参数列表的支持,而不是函数柯里化的概念。正如@TomaszNurkiewicz 指出的那样,仅使用某些参数实际上会导致部分应用函数,无论该函数是具有单个参数列表还是多个参数列表。在实践中,我认为差异是微不足道的,但我仍然认为保持术语直截了当。

标签: scala currying


【解决方案1】:

抛开理论动机(参见:Contrast with partial function application in Wikipedia on currying),有一个实际含义。当最后一个参数是代码块时,语法更简单,更易读。

比较以下方法:

def test1(name: String, callback: => Unit) {}
def test2(name: String)(callback: => Unit) {}

第二个方法调用看起来好多了,比较一下:

test("abc", {
    //some code
})

test2("abc") {
    //some code
}

【讨论】:

  • 很高兴有人在这里指出了部分函数应用。将 Scala 的 多个参数列表curried 函数 的概念混为一谈让我很头疼!
【解决方案2】:
  • 更好的语法:add(1) 而不是 add(1,_)
  • 类型推断从左到右参数列表。例如,这用于集合的折叠方法中。
  • 隐式参数列表也需要它们。

当然,您可以争辩说最后两个可能以不同的方式实现。

【讨论】:

    【解决方案3】:

    我不熟悉 currying 背后的理论(到目前为止),但我知道至少有一个具体的情况,currying 效果更好:调用带有一对花括号而不是括号的函数只能用于单参数职能。因此,您可以为具有两个参数列表且每个参数列表的柯里化函数执行此操作,但不适用于已部分应用于一个参数的普通函数。

    这在实现控制结构或 DSL 时特别有用,其中函数的某些参数本身就是匿名函数。这方面的一个例子来自 Scala 编程,第 9.4 节:

    val file = new File("date.txt")
    
    withPrintWriter(file) {
      writer => writer.println(new java.util.Date)
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-02-07
      • 1970-01-01
      • 1970-01-01
      • 2018-01-24
      • 1970-01-01
      • 2019-03-26
      • 2017-03-09
      相关资源
      最近更新 更多