5

我考虑重构一些当前采用类型参数ListSet具体类参数的方法签名List[Foo]——以使用重复参数代替:Foo*.

更新以下推理是有缺陷的,继续前进......
这将允许我使用相同的方法名称并根据参数类型重载它。List使用or是不可能的Set,因为List[Foo]List[Bar]擦除后具有相同的类型:List[Object]

在我的情况下,重构的方法可以很好地处理scala.Seq[Foo]重复参数的结果。我将不得不更改所有调用并向所有集合参数添加序列参数类型注释:baz.doStuffWith(foos:_*).

鉴于从集合参数切换到重复参数在语义上是等效的,这种变化是否会对性能产生一些我应该注意的影响?

scala 2.7._ 和 2.8 的答案是否相同?

4

3 回答 3

4

当 Scala 调用 Scala 可变参数方法时,该方法将接收一个扩展的对象Seq。当使用 进行调用时: _*,对象将按原样传递*,而不进行复制。以下是这方面的例子:

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)

笔记

  • AnArray作为 a 传递WrappedArray。但是,没有涉及到元素的复制,对 的更改WrappedArray将反映在Array.
于 2010-03-16T07:40:39.840 回答
3

您用 T* 替换 List[T] 的原因是有缺陷的:Scala 不允许重载

class Foo
{
   def t1(x : Int*) = println("Ints")
   def t1(x : Strings*) = println("Strings")
}

这将导致与在此处使用 List[Int]/List[String] 相同的编译器错误。

虽然有点笨拙,但您可以使用

class Foo
{
   def t1(x0 : Int,x : Int*) = println("Ints")
   def t1(x0 : String,x : Strings*) = println("Strings")
}

但这需要对第一个参数与其余参数进行特殊处理。

格。西尔维奥

于 2010-03-16T13:06:35.090 回答
0

用最简单的术语来说,与重复形式参数相对应的所有参数,无论其来源如何,都必须复制到某种顺序集合中以呈现给方法。具体使用何种序列的细节因 Scala 版本以及参数的来源而异。但不管这些细节如何,这都是一个 O(n) 操作,尽管每个项目的成本非常低。序列本身将至少有一个,有时甚至更多的实例分配。

兰德尔·舒尔茨

于 2010-03-16T03:27:49.547 回答