Reputation: 1995
There is something odd about partially applying a curried function with varargs. Consider this example:
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)
While I am aware of a previous question, I would still like to know why the compiler does this and if there is some clever solution in these cases.
Upvotes: 1
Views: 93
Reputation: 14224
This is because methods and functions are different things in Scala. Methods support type parameters, default and named arguments, varargs, implicit argument lists, etc.
When you do eta expansion method _
, the method is converted to a function which is simply an instance of a Function0
to Function22
trait, and doesn't support any of those features.
You can express function types with a shorthand Int => String
, or (A, B) => R
. Methods on the other hand have non-value types, and there is no general way to reference such a type in a Scala program.
If you want to have a callable variable, that supports varargs, or any other method features, you can return an object with an appropriate apply
method:
case class adder(a: Int) {
def apply(b: Int*) = b.map(_ + a)
}
Now it works:
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)
Upvotes: 2