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?
Rules for varargs:There can be only one variable argument in the method. Variable argument (varargs) must be the last argument.
Syntax of VarargsA variable-length argument is specified by three periods or dots(…). This syntax tells the compiler that fun( ) can be called with zero or more arguments. As a result, here, a is implicitly declared as an array of type int[].
(three dots) is used in the formal parameter of a method. A method that takes variable number of arguments is called a variable-arity method, or simply a varargs method.
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).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With