1

Possible Duplicate:
What is the type of a variable-length argument list in Scala?

I recently came across this post on parameter lists: https://stackoverflow.com/a/4684598/1287554 and I find it really interesting.

I also understand the use case as given below:

def fn(x:Int*) = x.sum                    //> fn: (x: Int*)Int  
fn(1,2,3)                                 //> res0: Int = 6

The obvious explanation I see is that it is some sort of syntactic sugar for the following code:

def fn(x:List[Int]) = x.sum               //> fn: (x: List[Int])Int
fn(List(1,2,3))                           //> res0: Int = 6

But I can't find any documentation about them. Can someone point me to some links which explains about this type of function parameters? Also, are they called parameter lists or something else? Maybe the reason I can't find anything is because I'm searching with the wrong name?

Community
  • 1
  • 1
Plasty Grove
  • 2,807
  • 5
  • 31
  • 42

2 Answers2

6

These are variable length argument lists (repeated parameters according to the specification, as Randall correctly pointed out in his answer), usually known as "varargs", the name of the K&R C library function that implemented such functionality.

For Scala, on the JVM level, arg: T* parameters are passed as a arg: Seq[T], usually through an WrappedArray.

Java, which has the same thing with the syntax T... arg, always pass the parameters as Array[T]. Scala recognizes Java varargs and can call them as well as Scala's.

One important difference between Scala varargs and Java varargs is the convention used to call methods implementing them passing not the parameters, but an object containing them. In Java, you can just pass an array:

public void m(String... args)

String[] list = new String[] { "a", "b", "c" };
m(list)

Whereas in Scala, you have to resort to a special syntax to make your meaning clear:

val list = Seq("a", "b", "c")
m(list: _*)

Also of note, you have a converse operator when pattern matching:

list match {
    case Seq(xs @ _*) => xs.size
    case _            => 0
}
Community
  • 1
  • 1
Daniel C. Sobral
  • 295,120
  • 86
  • 501
  • 681
  • Thanks, I didn't know that Java also had them or that it's been there since C! :/ – Plasty Grove Jan 16 '13 at 04:06
  • In your scala example of passing a Seq to the function, `m(list: _*)` works but `m(list: Int*)` doesn't. What does the underscore mean here? – Plasty Grove Jan 16 '13 at 04:18
  • 1
    @PlastyGrove It's not really underscore, it is `_*`, though a space is accepted there. It's a special syntax for passing a list as if it were multiple arguments, and not a combination of other features. – Daniel C. Sobral Jan 16 '13 at 18:41
3

To start, Scala calls them "repeated parameters," not "varargs."

The actual parameters corresponding to a repeated formal parameter are collected into a special kind of IndexedSeq implemented by WrappedArray:

scala> def mRP1(ints: Int*): Int = { printf("ints=%s%n", ints); ints.length }
mRP1: (ints: Int*)Int

scala> mRP1(1, 4, 9)
ints=WrappedArray(1, 4, 9)
res0: Int = 3

Note that because they are implementd by an IndexedSeq they have constant-time indexed access.

Randall Schulz
  • 26,420
  • 4
  • 61
  • 81
  • Thanks so much for the link! I've been searching without knowing what to call it. – Plasty Grove Jan 16 '13 at 04:07
  • I've shamelessly stolen all the extra information you put in to my own answer. :-) – Daniel C. Sobral Jan 16 '13 at 18:44
  • Actually, @om-nom-nom supplied the link to the on-line copy of Programming in Scala (1st ed.). – Randall Schulz Jan 16 '13 at 21:12
  • What you didn't show here but is actually interesting is the output of `mRP1(List(1,2,3): _*)`, which is `ints=List(1, 2, 3)`. So we know that the Scala compiler isn't boxing up the `Seq` when we use `_*` notation. Also, your claim that we have assurance of constant time indexed access does not seem to hold. (`List` has O(n) time for indexed access.) – john sullivan Jul 11 '13 at 13:00
  • Indeed. I guess that's an "optimization" in which a type-compatible and source of arguments is used directly rather than being copied to a `WrappedArray`. What's even more interesting (possibly alarming) is that the same optimization applies to mutable sequence arguments passed in this manner! – Randall Schulz Jul 11 '13 at 13:30
  • Interesting. I just checked the [lang spec](http://www.scala-lang.org/docu/files/ScalaReference.pdf), (section 4.6.2), which goes no further than to say you get a `scala.Seq` (which includes both mutable and immutable Seqs). – john sullivan Jul 15 '13 at 01:31