5

List現在、型またはSet具象クラスのパラメーターを受け取るいくつかのメソッド シグネチャをリファクタリングして、代わりに繰り返しパラメーターList[Foo]を使用することを検討しています。Foo*

更新次の推論には欠陥があります。先に進んで
ください...これにより、同じメソッド名を使用して、パラメーターの型に基づいてオーバーロードできます。これはListorを使用して行うことはできませんでしSetた。なぜならList[Foo]、 とList[Bar]は消去後に同じ型を持っているからです: List[Object]

私の場合、リファクタリングされたメソッドscala.Seq[Foo]は、繰り返されるパラメーターの結果で正常に機能します。すべての呼び出しを変更し、すべてのコレクション パラメーターにシーケンス引数型の注釈を追加する必要があります: baz.doStuffWith(foos:_*).

コレクション パラメーターから繰り返しパラメーターへの切り替えが意味的に同等であることを考えると、この変更はパフォーマンスに影響を与えるので注意が必要ですか?

scala 2.7._ と 2.8 の答えは同じですか?

4

3 に答える 3

4

Scala が Scala varargs メソッドを呼び出している場合、メソッドは を拡張するオブジェクトを受け取ります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は として渡されますWrappedArray。ただし、関係する要素のコピーはなく、 への変更WrappedArrayは に反映されますArray
于 2010-03-16T07:40:39.840 に答える
3

List[T]を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")
}

ただし、最初のパラメーターと残りのパラメーターを特別に処理する必要があります。

Gr。シルヴィオ

于 2010-03-16T13:06:35.090 に答える
0

簡単に言えば、繰り返される仮パラメーターに対応するすべての引数は、その起源に関係なく、メソッドに提示するために何らかの順次コレクションにコピーする必要があります。使用されるシーケンスの正確な種類の詳細は、Scala のバージョンと、場合によっては引数のソースによって異なります。ただし、これらの詳細に関係なく、アイテムあたりのコストはかなり低いですが、これは O(n) 操作です。シーケンス自体には、少なくとも 1 つ、場合によっては複数のインスタンスが割り当てられます。

ランドール・シュルツ

于 2010-03-16T03:27:49.547 に答える