5

Can anyone tell me why this limitation exists ? Is it related to JVM or Scala compiler ?

$ scala
Welcome to Scala version 2.10.4 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_79).
Type in expressions to have them evaluated.
Type :help for more information.

scala> def toText(ints: Int*, strings: String*) = ints.mkString("") + strings.mkString("")
<console>:7: error: *-parameter must come last
       def toText(ints: Int*, strings: String*) = ints.mkString("") + strings.mkString("")
Sudheer Aedama
  • 2,116
  • 2
  • 21
  • 39

2 Answers2

14

A method in Scala can have multiple varargs if you use multiple parameter lists (curried syntax):

scala> def toText(ints: Int*)(strings: String*) = 
         ints.mkString("") + strings.mkString("")

scala> toText(1,2,3)("a", "b")

res0: String = 123ab

Update: Multiple varargs in a single parameter list would create a syntax problem - how would the compiler know which parameter a given argument belongs to (where does one list of arguments end, and the next begin, especially if they are of compatible types?).

In theory, if the syntax of the language were modified so that one could distinguish the first and second argument lists (without currying), there's no reason this wouldn't work at the JVM level, because varargs are just compiled into an array anyway.

But I very much doubt that it's a common enough case to justify complicating the language further, especially when a solution already exists.

See also this related Java question and answer.

Community
  • 1
  • 1
DNA
  • 42,007
  • 12
  • 107
  • 146
  • While it's good to know that it works with currying, I was curious to know the reason why this limitation exists at all. Thanks. – Sudheer Aedama May 08 '15 at 21:59
  • 2
    One reason is the syntax - how would you know which parameter a given argument belongs to (where does one list of arguments end, and the next begin?), especially if they were of compatible types? – DNA May 08 '15 at 22:00
4

Scala is based on Java Virtual Machine, which is set to accept varargs only as the last argument, only one per method arguments set. No working this around, this is how the compiler works.

To put it into perspective, imagine a method signature like this:

someMethod(strings1: String*, strings2: String*)

Let's say you pass 4 separate Strings when calling it. The compiler would not know which String object belongs to which vararg.

Kelevandos
  • 7,024
  • 2
  • 29
  • 46
  • Sorry but this just erroneous. The JVM doesn't even know what a Scala varargs method is. The compiler transforms a varargs method into a completely normal method taking a `Seq` as argument, and this what the JVM sees. @DNA's answer is the correct one. – sjrd May 09 '15 at 06:21
  • I can not agree. His answer describes a kind of workaround, while I tried to answer the question asked. The question relates to the basics of JVM and the way it interprets the varargs in its bytecode. – Kelevandos May 09 '15 at 07:08
  • But it *doesn't* have anything to do with the JVM. The JVM doesn't *see* anything that remotely looks like varargs. It is all *compiled away* as non-varargs. There is *no such thing* as "the way [the JVM] interprets the varargs in its bytecode" because there is no varargs in the bytecode. @DNA also comments on their answer the reason *scalac* doesn't like it: you cannot know where the two varargs are separated. – sjrd May 09 '15 at 10:31
  • There is nothing like varargs in bytecode, you are right. Varargs are interpreted as an array of objects, which can be null, have no elements, have one element or many elements. This is how Java works and Scala, as a JVM language, did not reinvent the wheel, it works the same. – Kelevandos May 09 '15 at 13:00