我可以定义以下两个函数:
def add(a: Int, b: Int, c: Int) = a + b + c
这导致
add: (a: Int, b: Int, c: Int)Int
和
val add2 = (a: Int, b: Int, c: Int) => a + b + c
这导致
add2: (Int, Int, Int) => Int = <function3>
这两个函数完全相同,但以不同的方式定义,我不明白的是,如果我继续并按如下方式定义部分应用的函数:
def a = add _
这导致
a: (Int, Int, Int) => Int = <function3>
如预期的那样,一个函数接受3个参数并返回一个Int,但如果我这样做
def a2 = add2 _
这导致
a2: () => (Int, Int, Int) => Int = <function0>
这似乎是一个不带参数的函数,并返回一个带有3个Int参数并返回Int的函数。为什么会这样?有人可以解释一下发生了什么吗?
感谢
答案 0 :(得分:9)
这是Scala的一个奇怪的副作用,实际上没有(用户可访问的)字段,而是拥有所有内容的访问者(getter)。观察:
scala> val i = 1
i: Int = 1
scala> i _
res0: () => Int = <function0>
原因是i
实际上是底层(隐藏,不可访问)字段的访问者(def i: Int
)。由于它只是一种方法,_
会将其转换为函数。访问器不带任何参数,这就是为什么你有一个不带参数的函数。
答案 1 :(得分:2)
Scala既有功能又有方法,它们并不完全相同。
def add(a: Int, b: Int, c: Int) = a + b + c
哪个定义了一个方法(不是函数!!)。
val add2 = (a: Int, b: Int, c: Int) => a + b + c
为add2分配了一个函数值(不是方法!!)。
方法不能是最终值,而函数可以:
scala> add
<console>:9: error: missing arguments for method add;
follow this method with `_' if you want to treat it as a partially applied function
add
^
scala> add2
res1: (Int, Int, Int) => Int = <function3>
scala> val a = add
<console>:8: error: missing arguments for method add;
follow this method with `_' if you want to treat it as a partially applied function
val a = add
^
scala> val a2 = add2
a2: (Int, Int, Int) => Int = <function3>
在方法名称后面编写下划线可以将方法显式转换为函数:
scala> add _
res2: (Int, Int, Int) => Int = <function3>
但是如果你在一个值之后写一个下划线,它将转换为一个函数,该函数不带任何参数类型的返回类型:
scala> val s = ""
s: String = ""
scala> val i = 1
i: Int = 1
scala> s _
res3: () => String = <function0>
scala> i _
res4: () => Int = <function0>
因此,如果值本身是一个函数,在它之后写一个下划线将得到一个新的函数,该函数不带有返回类型函数的参数:
scala> add2 _
res5: () => (Int, Int, Int) => Int = <function0>
答案 2 :(得分:1)
效果在Rex Kerr's answer中有明确说明,但您应注意add2
是已经代表部分应用功能的值,例如代表。
为了演示,您可以比较add1 _
表达式和add2
值的类型。
scala> def getManifest[T](x:T)(implicit m:scala.reflect.Manifest[T]) = m
getManifest: [T](x: T)(implicit m: scala.reflect.Manifest[T])scala.reflect.Manifest[T]
scala> getManifest(add1 _) == getManifest(add2)
res14: Boolean = true