Skip to main content

Recursive varargs methods in Scala

Posted by cayhorstmann on October 13, 2009 at 3:36 PM PDT

And now for something entirely different...one of my students asked how to write a recursive function in Scala with varargs. Apparently, the internet has lots of articles complaining about the challenge of calling Java varargs methods from Scala, but this particular issue did not google well. Here goes...

In Scala, you declare varargs like this:

def sum(args: Int*) = {
  var result = 0
  for (arg <-args.elements) result += arg
  result
}

Think of Int* as a sequence of 0 or more integers. In Java, an int... is transformed into an int[], and in Scala, an Int* becomes a Seq[Int].

Of course, you can call

sum(1,2,3,4,5)

 

But you can't call

sum(1 to 5)

What gives? 1 to 5 is a Range[Int], and that's a subtype of Seq[Int]. But unlike Java, Scala insists that you pass a sequence of Int to sum, not a Seq[Int].

The remedy, as explained in the Scala Reference Section 4.6.2, is to call

sum(1 to 5 : _*)

that is, 1 to 5 as a sequence of something.

My students ran into this when trying to write a recursive function with varargs. The obvious

def sum(args: Int*) : Int = 
  if (args.length == 0)
    0 else
    args.head + sum(args.tail)

doesn't work. The trick is again to insert the : _* cast:

def sum(args: Int*) : Int = 
  if (args.length == 0)
    0 else
    args.head + sum(args.tail : _*)
Related Topics >>

Comments

Clearer than _*

Cay, is there a long-hand version of _* that is a bit more clear?

I don't think there is. Int*

I don't think there is. Int* isn't a type, so you can't cast to it. I don't think it is a terrible notation, and coming up with another one would just add more complexity.