Saturday, December 8, 2012
Scala syntax bug?

I'm running into a weird situation in some Scala code I'm writing (more on why in a later post), and I'm curious to know from my Scala-ish followers if this is a bug or intentional/"by design".

First of all, I can define a function that takes a variable argument list, like so:

    def varArgs(key:String, args:Any*) = {
And this is good.

I can also write a function that returns a function, to be bound and invoked, like so:

    val good1 = (key:String) => {
And this also works.

But when I try to combine these two, I get an interesting error:

    val bad3 = (key:String, args:Any*) => {
    bad3("Howdy", 1, 2.0, "3")
... which yields the following compilation error:
Envoy.scala:169: error: ')' expected but identifier found.
    val bad3 = (key:String, args:Any*) => {
one error found
... where the "^" is lined up on the "*" in the "args" parameter, in case the formatting isn't clear.

Now, I can get around this by using a named function and returning it as a partially-applied function:

    val good2 = {
      def inner(key:String, args:Any*) = {
      inner _
    good2("Howdy", 1, 2.0, "3")
... but it's a pain. Can somebody tell me why "bad3", above, refuses to compile? Am I not getting the syntax right here, or is this a legit bug in teh compiler?

Saturday, December 8, 2012 7:07:20 AM (Pacific Standard Time, UTC-08:00)
It's not a bug, it specified as that and of course discussed at stackoverflow:

The reason that this does not work is "This looks tempting at first, but it would drag in a lot of complexity" according to comments on the stackoverflow thread mentioned above.
Saturday, December 8, 2012 2:31:29 PM (Pacific Standard Time, UTC-08:00)
Anonymous methods are implemented with Function0 to 23 internally by scala. I don't think any of them has a signature to take a variant length of parameters. So it's "by design" this is not compile-able.
Sunday, December 9, 2012 1:02:25 AM (Pacific Standard Time, UTC-08:00)
@tcmaster I don't think that is the problem. A varargs parameter is really just a single parameter of Array type with some syntactic sugar.
Monday, December 10, 2012 7:41:17 AM (Pacific Standard Time, UTC-08:00)
The syntax is a little misleading here; perhaps it is being too cute. The Any* syntax for varargs makes it look like Any* is itself a type. Really, the * is an annotation on the method parameter, not on the type.

When you write down a function type using the T1=>T2 syntax, both T1 and T2 need to be plain old bona fide types. Scala provides oodles of kinds of types, but vararg types are not one of them.

In practical code, the way out is to explicitly use a sequence type. In fact, if you look at the inferred type for good2, you will see it involves Seq[Any] rather than Any*.

Comments are closed.