Frage

Ich halte Refactoring einige Methodensignaturen, die derzeit Parameter vom Typ List oder Set von konkreten Klassen --List[Foo]-- Gebrauch nehmen wiederholten Parameter statt: Foo*.

  

Aktualisieren : Nach Argumentation fehlerhaft ist, bewegen sich entlang ...
  Dies würde erlauben Sie mir die gleiche Methode Namen zu verwenden und es Überlastung basierend auf dem Parameter-Typ. Das war nicht möglich List oder Set verwenden, weil List[Foo] und List[Bar] gleichen Typen nach dem Löschen haben. List[Object]

In meinem Fall der Überarbeitete Methoden funktionieren mit scala.Seq[Foo], dass den Ergebnissen aus den wiederholten Parametern. Ich möchte alle die Anrufungen sich ändern müssen, und fügen Sie ein Sequenz Argument Typanmerkung für alle Erfassungsparameter. baz.doStuffWith(foos:_*)

Da die von der Sammlung Parameter wiederholten Parameter Umschalten semantisch äquivalent ist, geht diese Änderung eine gewisse Auswirkungen auf die Leistung haben, dass ich bewusst sein sollten?

Ist die Antwort gleich für scala 2.7._ und 2.8?

War es hilfreich?

Lösung

Wenn Scala ist eine Scala varargs Methode aufrufen, wird die Methode ein Objekt erhalten, die Seq erstreckt. Wenn der Anruf mit : _* gemacht wird, wird das Objekt als übergeben werden soll * , ohne sie zu kopieren. Hier sind einige Beispiele dafür:

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)

Hinweis

  • Ein Array als WrappedArray geben. Es gibt kein Kopieren von Elementen beteiligt, aber, und Änderungen an den WrappedArray werden im Array reflektiert werden.

Andere Tipps

Ihr Grund für den Ersatz Liste [T] mit T * ist fehlerhaft: Scala wird nicht zulassen, eine Überlastung wie

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

Dieses im gleichen Compiler-Fehler führen wird, wie mit List [Int] / List [String] hier.

Obwohl ein bisschen ungeschickt könnten Sie

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

aber das erfordert eine besondere Behandlung des ersten Parameters im Vergleich zu dem Rest.

Gr. Silvio

In der einfachstenen Form, alle Argumente, dass entspricht einen wiederholten formalen Parameter, unabhängig von ihrer Herkunft, muss auf das Verfahren zu einer sequentiellen Sammlung von irgendeiner Art für die Präsentation kopiert werden. Die Einzelheiten genau, welche Art von Sequenz verwendet wird, variieren mit Scala Version und möglicherweise mit der Quelle der Argumente. Aber unabhängig von diesen Details ist es eine O (n) -Operation, wenn die Kosten pro Stück ziemlich niedrig ist. Es wird für die Sequenz selbst eine und manchmal mehr wiesen Zuweisungen mindestens sein.

Randall Schulz

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top