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
}
我想知道为什么 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 ofList
fortail
, and therefore forgot that you need to pass a number todrop
. You might writeprintln(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 thisprintln
would always be to output]<function>
! [Since] the expressiondrop
would have been treated as any function object andprintln
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 启发的功能中,大括号 (
处看起来非常 C-like 的语法{}
) 可以替换单个参数列表周围的括号。此功能有助于在 call-site:
// 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
}