Descomposición de coincidencias Scala en operador infijo
-
06-07-2019 - |
Pregunta
Estoy tratando de entender la implementación de List
s en Scala. En particular, estoy tratando de entender cómo puedes escribir expresiones de coincidencia utilizando un operador infijo, por ejemplo:
a match {
case Nil => "An empty list"
case x :: Nil => "A list without a tail"
case x :: xs => "A list with a tail"
}
¿Cómo se permite que la expresión de coincidencia sea x :: xs
en lugar de List (x, xs)
?
Solución
La respuesta de Jay Conrad es casi correcta. Lo importante es que en algún lugar hay un objeto llamado ::
que implementa el método unapply
, devolviendo el tipo Option [(A, Lista [A])]
. Por lo tanto:
object :: {
def unapply[A](ls: List[A]): Option[(A, A)] = {
if (ls.empty) None
else Some((ls.head, ls.tail))
}
}
// case objects get unapply for free
case object Nil extends List[Nothing]
En el caso de ::
y List
, este objeto resulta del hecho de que ::
es una clase de caso que extiende el rasgo List
. Sin embargo, como muestra el ejemplo anterior, no tiene que ser una clase de caso en absoluto.
Otros consejos
Creo que :: es en realidad una clase (que es una subclase de Lista ), por lo que decir x :: xs
es mayormente equivalente a List (x, xs)
.
Puede hacer esto con otras clases de casos que tienen nombres de operador. Por ejemplo:
case class %%%(x: Int, y: Int)
a match {
case x %%% y => x + y
}
¿Cómo se permite que la expresión de coincidencia sea x :: xs en lugar de List (x, xs)?
Para responder esta pregunta:
Cuando se ve como un patrón , un infijo operación como p op q es equivalente a op (p, q) . Es decir, el infijo El operador op se trata como un patrón constructor .
(Programación en Scala, 1ª ed., p. 331)
Consulte también preguntas sobre las clases de casos de scala