JOB REFERRALS
    ON THIS PAGE
    ARCHIVES
    CATEGORIES
    BLOGROLL
    LINKS
    SEARCH
    MY BOOKS
    DISCLAIMER
 
 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*) = {
      println(key)
      println(args)
      true
    }
    varArgs("Howdy")
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) => {
      println(key)
      true
    }
    good1("Howdy")
And this also works.

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

    val bad3 = (key:String, args:Any*) => {
        println(key)
        println(args)
        true
    }
    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*) = {
        println(key)
        println(args)
        true
      }
      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?


Java/J2EE | Languages | Reading | Scala

Saturday, December 8, 2012 12:20:34 AM (Pacific Standard Time, UTC-08:00)
Comments [4]  |  Related posts:
Tech Predictions, 2014
On (Free) Speaking
On Endings
Seattle (and other) GiveCamps
On speakers, expenses, and stipends
On startups
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: http://stackoverflow.com/a/8623215/66686

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.
tcmaster
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.