scala 参数偏应用

scala parameter partial application

我想知道为什么 Scala 不使用与其他函数式编程语言相同的函数部分应用风格?

多个参数列表背后的好处或想法是什么?

这与Scala基于点演算有什么关系,还是对JVM的优化?

对我来说它增加了问题,如果有人将函数定义为:

def f(x: Int, y: Int): Int

而不是:

def f(x: Int)(y: Int): Int

我不能做部分应用,简单的方法。

像这样定义大多数函数是否是一个好习惯(这是默认方法):

def f(x: Int)(y: Int)(z: Int): Int

Odersky 等人在 Programming In Scala 中报道了它。

Scala's syntax for partially applied functions highlights a difference in the design trade-offs of Scala and classical functional languages, such as Haskell or ML. In these languages, partially applied functions are considered the normal case. Furthermore, these languages have a fairly strict static type system that will usually highlight every error with partial applications that you can make. Scala [bears a relation to languages such as Java] where a method that's not applied to all of its arguments is considered an error. Furthermore, the object-oriented tradition of subtyping and a universal root type accepts some programs that would be considered erroneous in classical functional languages.

For instance, say you mistook the drop(n: Int) method of List for tail, and therefore forgot that you need to pass a number to drop. You might write println(drop). Had Scala adopted the classical functional tradition that partially applied functions are OK everywhere, this code would type check. However, you might be surprised to find out that the [side effect of this println would always be to output] <function>! [Since] the expression drop would have been treated as any function object and println takes objects of any type, this would have compiled, but it would have an unexpected result.

To avoid situations like this, Scala normally requires you to specify function arguments that are left out explicitly, even if the indication is as simple as _. [The _ can be left off, however] only when a function type is expected.

f(x)(y) 符号往往仅在部分应用有明显效用(或作为作者认可部分应用的信号)或为了利用与其他应用的相互作用时才使用Scala 方面:

  • 类型推断由 argument-list 发生 parameter-list,因此可以根据第一个参数列表为以后的参数列表修复类型。这可以节省一些类型界限。考虑 Option.map(f).getOrElse(a)(其中 a 可以是 f 结果类型的任何超类型的实例)与 Option.fold(a)(f)(其中 a 的类型约束f).

    的结果类型
  • 在一个可能受 Perl 启发的功能中,大括号 ({}) 可以替换单个参数列表周围的括号。此功能有助于在 call-site:

    处看起来非常 C-like 的语法
// NB: doesn't support early exit (except by throwing an exception...)
def myWhile(condition: => Boolean)(body: => Unit): Unit = {
  @annotation.tailrec
  def spin: Unit =
    if (condition) {
      body
      spin
    } else ()

  spin
}

var x: Int = 0
myWhile (x < 4) {
  println("whee!")
  x += 1
}