Pregunta

Considero refactorización pocas firmas de los métodos que actualmente toman parámetros de List tipo o Set de clases concretas --List[Foo]-- utilizar repitieron los parámetros en su lugar: Foo*.

  

Actualizar Siguiendo el razonamiento es defectuoso, moverse a lo largo ...
  Esto me permite utilizar el mismo nombre de método y sobrecargarla basado en el tipo de parámetro. Esto no era posible utilizando List o Set, porque List[Foo] y List[Bar] tienen mismo tipo después de borrado:. List[Object]

En mi caso los métodos refactorizado funcionar bien con scala.Seq[Foo] que resulta del parámetro repetido. Tendría que cambiar todas las invocaciones y añadir un argumento sequence tipo de anotación a todos los parámetros de recogida:. baz.doStuffWith(foos:_*)

Dado que el cambio de parámetro a la colección de parámetros repetida es semánticamente equivalente, este cambio no tienen algún impacto en el rendimiento que debería tener en cuenta?

¿Es la respuesta para la misma Scala 2.7._ y 2,8?

¿Fue útil?

Solución

Cuando Scala está llamando a Scala varargs método, el método recibir un objeto que se extiende Seq. Cuando la llamada se realiza con : _*, el objeto se pasa como es * , sin copiar. Estos son ejemplos de esto:

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)

Nota:

  • Una Array se pasa como un WrappedArray. No hay ninguna copia de los elementos involucrados, sin embargo, y los cambios en el WrappedArray se reflejarán en el Array.

Otros consejos

Su razón para reemplazar Lista [T] con T * es defectuoso: Scala no permitirá que la sobrecarga como

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

Esto resultará en el mismo error de compilación como el uso de la lista [Int] / Lista [String] aquí.

Aunque un poco torpe podría utilizar

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

pero que requiere tratamiento especial de la primera parámetro frente al resto.

Gr. Silvio

En los términos más simples, todos los argumentos que se corresponden con unas repetidas parámetros formales, independientemente de su origen, se debe copiar en una colección secuencial de algún tipo para su presentación al método. Los detalles de exactamente qué se utiliza tipo de secuencia varían con la versión Scala y posiblemente con la fuente de los argumentos. Pero a pesar de esos detalles, es un O (n) la operación, aunque el coste por artículo es bastante bajo. No habrá al menos uno y a veces más asignaciones de instancia para la propia secuencia.

Randall Schulz

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top