Coste de utilización de parámetros repetidos
-
20-09-2019 - |
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 utilizandoList
oSet
, porqueList[Foo]
yList[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?
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 unWrappedArray
. No hay ninguna copia de los elementos involucrados, sin embargo, y los cambios en elWrappedArray
se reflejarán en elArray
.
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