Reputation: 5270
If I define the following function to return a function:
def foo(): (Int*) => String = { is =>
is.map(_.toString).mkString(", ")
}
And then try to reference it:
val bar = foo()
bar(1, 2, 3)
I get the compiler error
Too many arguments (3) for method apply...
But when I explicitly define the reference type it compiles fine:
val bar2: (Int*) => String = foo()
bar2(4, 5, 6)
Is there any way I can define my function foo()
without needing this explicit reference type?
Upvotes: 10
Views: 696
Reputation: 139038
This is a known bug, which was "fixed" in Scala 2.13 by removing the ability to use *
in types outside of method signatures at all.
If you only care about pre-2.13 Scala versions, you can use the workaround you've identified—explicitly annotate the function variable with the starred type. If you need to support 2.13, you can do something like this, thanks to Scala's single abstract method syntax:
trait MyVarargsFunc[-A, +B] {
def apply(is: A*): B
}
val f: MyVarargsFunc[Int, String] = is => is.map(_.toString).mkString(", ")
Or if you want to get really fancy:
trait *=>[-A, +B] { def apply(is: A*): B }
val f: Int *=> String = is => is.map(_.toString).mkString(", ")
And then:
scala> f(1, 2, 3)
res0: String = 1, 2, 3
This will also work on 2.12 (I checked), and it should work on 2.11 with -Xexperimental
(and it'll work even on 2.10 or vanilla 2.11 if you instantiate MyVarargsFunc
explicitly—you just don't get the nice function literal syntax).
Upvotes: 13