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

时间:2015-05-16 16:25:48

标签: scala

以下内容:

val add = (a: Int, b: Int) => a + b 

转换为:

object add extends Function2[Int, Int, Int] {
  def apply(a: Int, b: Int) = a + b
}

,而

val a1 = add(_: Int, 3)

转换为:

object a1 extends Function1[Int, Int] {
  def apply(x: Int): Int = {
    add(x, 3)
  }
}

但是当我这样做时:

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

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

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

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

a2()(1, 2)

1 个答案:

答案 0 :(得分:9)

add已经是Function2[Int, Int, Int]。如果您希望a2具有相同的类型,那么简单的赋值就足够了。

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

scala> a2(1, 2)
res3: Int = 3

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

def add(a: Int, b: Int): Int = a + b

然后,我们会使用add _来获取eta-expansion以赋值。

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

scala> a2(1, 2)
res4: Int = 3

但是add 已经一个函数,因此下划线具有不同的含义。 add现在是,而不是方法。由于add,因此它类似于无参数方法,它返回Function2[Int, Int, Int]。如果我们尝试对其进行eta扩展,我们会得到() => Function2[Int, Int, Int]

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

scala> val a = 1
a: Int = 1

scala> val a2 = a _
a2: () => Int = <function0>