nosewheelie

Technology, mountain biking, politics & music.

Scala varags handling

with 2 comments

Mainly for my future reference, a quick overview of how Scala appears to handle varargs. The Scala book doesn’t offer an explanation currently so this is all derived through experiments using Scala 2.6.1.

To make a method accept a variable number of arguments, it is defined as follows.

scala> def foo(s: String*) { println(s) }
foo: (String*)Unit

Like Java, Scala requires the vararg to be the last parameter to the function. Once in your method, the parameter is of type Array[String] (more generally Array[A] where A is a type parameter).

scala> def foo(s: String) { println(s) }
foo: (String)Unit

scala> foo("hello")
hello

scala> def foo(s: String*) { println(s) }
foo: (String*)Unit

scala> foo("hello", "world")
Array(hello, world)

scala> def foo(s: String*, t: Int) { println(s) }
:4: error: *-parameter must come last
       def foo(s: String*, t: Int) { println(s) }
               ^

Unlike Java 1.5, you must explicitly declare your functions to accept variable arguments, you can not declare a parameter to be an Array[A] and have the runtime perform an automatic conversion for you (I believe this may have something to do with Java 13/1.4 compatibility). So the following is not equivalent to the above and will not compile:

scala> def foo(s: Array[String]) { println(s) }
foo: (Array[String])Unit

scala> foo("hello", "world")
:6: error: wrong number of arguments for method foo: (Array[String])Unit
       foo("hello", "world")
       ^

Likewise, you can not declare something to take a varargs parameter and call it as if it’s an array (as you can in Java):

scala> def foo(s: String*) { println(s) }
foo: (String*)Unit

scala> foo(Array("hello", "world"))
:6: error: no type parameters for method apply: (A*)Array[A] in object Array exist so that it can be applied to arguments (java.lang.String,java.lang.String)
 --- because ---
result type Array[A] is incompatible with expected type String
       foo(Array("hello", "world"))
           ^

There’s also some odd rules around overloading of functions, due to erasure:

scala> object Foo { def foo(ss: String*) = println(ss); def foo(is: Int*) = println(is) }
:4: error: double definition:
method foo:(Int*)Unit and
method foo:(String*)Unit at line 4
have same type after erasure: (Seq)Unit
       object Foo { def foo(ss: String*) = println(ss); def foo(is: Int*) = println(is) }

The variable argument gets the type Seq[A] (the actual underlying runtime type is Array[A]), and owing to the wonderful properties of erasure, both these methods have the same signature.

Written by Tom Adams

January 22nd, 2008 at 12:04 pm

Posted in Scala

2 Responses to 'Scala varags handling'

Subscribe to comments with RSS or TrackBack to 'Scala varags handling'.

  1. Not really related, but it would be nice if the book/docs were in plain(ish) HTML form. I kind of cuss under my breath each time I click on a PDF link (although on OSX its not so bad).

    Michael Neale

    22 Jan 08 at 1:08 pm

  2. Yeah, I see no reason why “the book” for example cannot be produced in HTML also, from what I’ve gleaned about their build process would seem to be doable. I don’t mind PDFs though, Preview in Leopard is much better and very fast, so it’s quite good for looking up terms such as “varargs”, etc. Makes it easy to spot mistakes/oversights also.

    Tom Adams

    22 Jan 08 at 8:26 pm

Leave a Reply