When Scala is calling a Scala varargs method, the method will receive an object that extends Seq
. When the call is made with : _*
, the object will be passed as is*, without copying. Here are examples of this:
scala> object T {
| class X(val self: List[Int]) extends SeqProxy[Int] {
| private val serial = X.newSerial
| override def toString = serial.toString+":"+super.toString
| }
| object X {
| def apply(l: List[Int]) = new X(l)
| private var serial = 0
| def newSerial = {
| serial += 1
| serial
| }
| }
| }
defined module T
scala> new T.X(List(1,2,3))
res0: T.X = 1:List(1, 2, 3)
scala> new T.X(List(1,2,3))
res1: T.X = 2:List(1, 2, 3)
scala> def f(xs: Int*) = xs.toString
f: (Int*)String
scala> f(res0: _*)
res3: String = 1:List(1, 2, 3)
scala> f(res1: _*)
res4: String = 2:List(1, 2, 3)
scala> def f(xs: Int*): Seq[Int] = xs
f: (Int*)Seq[Int]
scala> def f(xs: Int*) = xs match {
| case ys: List[_] => println("List")
| case _ => println("Something else")
| }
f: (Int*)Unit
scala> f(List(1,2,3): _*)
List
scala> f(res0: _*)
Something else
scala> import scala.collection.mutable.ArrayBuffer
import scala.collection.mutable.ArrayBuffer
scala> def f(xs: Int*) = xs match {
| case ys: List[_] => println("List")
| case zs: ArrayBuffer[_] => zs.asInstanceOf[ArrayBuffer[Int]] += 4; println("Array Buffer")
| case _ => println("Something else")
| }
f: (Int*)Unit
scala> val ab = new ArrayBuffer[Int]()
ab: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer()
scala> ab + 1
res11: scala.collection.mutable.Buffer[Int] = ArrayBuffer(1)
scala> ab + 2
res12: scala.collection.mutable.Buffer[Int] = ArrayBuffer(1, 2)
scala> ab + 3
res13: scala.collection.mutable.Buffer[Int] = ArrayBuffer(1, 2, 3)
scala> f(ab: _*)
Array Buffer
scala> ab
res15: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 3, 4)
Note
- An
Array
is passed as a WrappedArray
. There's no copying of elements involved, however, and changes to the WrappedArray
will be reflected in the Array
.