为什么这个部分应用程序不能编译?

Tyr*_*ter 6 scala

下列:

val add = (a: Int, b: Int) => a + b 
Run Code Online (Sandbox Code Playgroud)

转换为:

object add extends Function2[Int, Int, Int] {
  def apply(a: Int, b: Int) = a + b
}
Run Code Online (Sandbox Code Playgroud)

val a1 = add(_: Int, 3)
Run Code Online (Sandbox Code Playgroud)

转换为:

object a1 extends Function1[Int, Int] {
  def apply(x: Int): Int = {
    add(x, 3)
  }
}
Run Code Online (Sandbox Code Playgroud)

但当我这样做时:

scala> val a2 = add _
a2: () => (Int, Int) => Int = <function0>
Run Code Online (Sandbox Code Playgroud)

然后调用a2,它会抛出一个错误:

scala> a2(1, 2) 
<console>:11: error: too many arguments for method apply: ()(Int, Int) => Int in trait Function0
              a2(1, 2)
                ^
Run Code Online (Sandbox Code Playgroud)

为什么是这样?为什么以下工作?

a2()(1, 2)
Run Code Online (Sandbox Code Playgroud)

Mic*_*jac 9

add已经是一个Function2[Int, Int, Int].如果你想a2拥有相同的类型,那么简单的赋值就足够了.

scala> val a2 = add
a2: (Int, Int) => Int = <function2>

scala> a2(1, 2)
res3: Int = 3
Run Code Online (Sandbox Code Playgroud)

您正在考虑的是将方法扩展为函数.如果我们有:

def add(a: Int, b: Int): Int = a + b
Run Code Online (Sandbox Code Playgroud)

然后,我们将使用add _eta-expansion来赋值.

scala> def a2 = add _
a2: (Int, Int) => Int

scala> a2(1, 2)
res4: Int = 3
Run Code Online (Sandbox Code Playgroud)

不过add已经一个功能,所以下划线具有不同的含义.add现在是一个价值而不是一种方法.由于add是一个,它就像一个返回a 的无参数方法Function2[Int, Int, Int].如果我们试图对其进行eta扩展,我们就会得到() => Function2[Int, Int, Int].

考虑一个简单的例子,我们有一个简单的例子val a = 1.a与返回1(def a = 1)的无参数方法基本相同.如果我试图获得eta扩展,我会得到() => Int.

scala> val a = 1
a: Int = 1

scala> val a2 = a _
a2: () => Int = <function0>
Run Code Online (Sandbox Code Playgroud)