用varargs定义和调用部分应用的函数?

时间:2017-11-10 09:19:18

标签: scala

使用varargs部分应用curried函数有些奇怪。考虑这个例子:

def adder(a: Int)(b: Int*) = b.map(_ + a) 

adder(1)(1,2,3,4)     // res1: Seq[Int] = ArrayBuffer(2, 3, 4, 5)
val add2 = adder(2) _ // add2: Seq[Int] => Seq[Int]
add2(1,2,3,4)         // Fails to compile
add2(Seq(1,2,3,4)     // res3: Seq[Int] = List(3, 4, 5, 6)

虽然我知道previous question,但我仍然想知道为什么编译器会这样做以及在这些情况下是否有一些聪明的解决方案。

1 个答案:

答案 0 :(得分:2)

这是因为Scala中的方法和函数是不同的东西。方法支持类型参数,默认和命名参数,varargs,隐式参数列表等。

当您进行eta扩展method _时,该方法将转换为一个函数,该函数只是Function0Function22特征的一个实例,并且不支持任何那些功能。

您可以使用速记Int => String(A, B) => R来表达函数类型。另一方面,方法有non-value types,并且在Scala程序中没有通用的方法来引用这种类型。

如果您想拥有一个可调用的变量,它支持varargs或任何其他方法功能,您可以使用适当的apply方法返回一个对象:

case class adder(a: Int) {
  def apply(b: Int*) = b.map(_ + a)
}

现在可行:

scala> adder(1)(1,2,3,4)
res1: Seq[Int] = ArrayBuffer(2, 3, 4, 5)

scala> val add2 = adder(2)
add2: adder = adder(2)

scala> add2(1,2,3,4)
res2: Seq[Int] = ArrayBuffer(3, 4, 5, 6)