ultra signo recontra que prefijos not mega mas intensivos hiper google funciona filetype como comandos comando busqueda avanzada and list scala operators prepend cons

signo - ¿Cuál es la diferencia entre `::` y `+:` para anteponer a una lista)?



super hiper mega ultra recontra (2)

List tiene 2 métodos que se especifican para anteponer un elemento a una lista (inmutable):

  • +: (implementando Seq.+: , y
  • :: (definido solo en la List )

+: técnicamente tiene una firma de tipo más general-

def +:[B >: A, That](elem: B)(implicit bf: CanBuildFrom[List[A], B, That]): That def ::[B >: A](x: B): List[B]

- pero ignorando lo implícito, que de acuerdo con el mensaje de doc simplemente requiere That sea List[B] , las firmas son equivalentes.

¿Cuál es la diferencia entre List.+: Y List.:: ? Si son de hecho idénticos, supongo que +: sería preferible evitarlos según la List implementación concreta. Pero ¿por qué se definió otro método público y cuándo lo llamaría el código del cliente?

Editar

También hay un extractor para :: coincidencia de patrones, pero me pregunto acerca de estos métodos particulares.

Ver también: concatenación de lista Scala, ::: vs ++


La mejor forma de determinar la diferencia entre ambos métodos es buscarlo en el código fuente.

La source de ::

def ::[B >: A] (x: B): List[B] = new scala.collection.immutable.::(x, this)

La source de +: :

override def +:[B >: A, That](elem: B)(implicit bf: CanBuildFrom[List[A], B, That]): That = bf match { case _: List.GenericCanBuildFrom[_] => (elem :: this).asInstanceOf[That] case _ => super.+:(elem)(bf) }

Como puede ver, para List , ambos métodos hacen uno y el mismo (el compilador elegirá List.canBuildFrom para el argumento CanBuildFrom ).

Entonces, ¿qué método usar? Normalmente uno elegiría la interfaz ( +: que la implementación ( :: pero como List es una estructura de datos general en lenguajes funcionales, tiene sus propios métodos que son ampliamente utilizados. Muchos algoritmos se construyen de la misma forma que funciona List . Por ejemplo, encontrará muchos métodos que anteponen elementos individuales a List o llaman a los métodos de head o tail convenientes porque todas estas operaciones son O(1) . Por lo tanto, si trabaja localmente con una List (dentro de métodos o clases individuales), no hay problema para elegir los métodos específicos de la List . Pero si desea comunicarse entre clases, es decir, si desea escribir algunas interfaces, debe elegir la interfaz Seq más general.


+: es más genérico, ya que permite que el tipo de resultado sea diferente del tipo de objeto al que se llama. Por ejemplo:

scala> Range(1,4).+:(0) res7: scala.collection.immutable.IndexedSeq[Int] = Vector(0, 1, 2, 3)