Décomposition par correspondance de Scala sur l'opérateur infixe
-
06-07-2019 - |
Question
J'essaie de comprendre la mise en oeuvre de List
dans Scala. En particulier, j'essaie de comprendre comment vous pouvez écrire des expressions de correspondance à l'aide d'un opérateur infixe, par exemple:
a match {
case Nil => "An empty list"
case x :: Nil => "A list without a tail"
case x :: xs => "A list with a tail"
}
Comment l'expression de correspondance est-elle autorisée à être x :: xs
plutôt que List (x, xs)
?
La solution
La réponse de Jay Conrad est presque exacte. L’important est que quelque part se trouve un objet nommé ::
qui implémente la méthode unapply
, renvoyant le type Option [(A, Liste [A])]
. Ainsi:
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]
Dans le cas de ::
et de List
, cet objet découle du fait que ::
est une classe de cas qui étend le trait List
. Cependant, comme le montre l'exemple ci-dessus, il n'est pas obligé d'être une classe de cas.
Autres conseils
Je crois que :: est en fait une classe (qui est une sous-classe de List ), en disant x :: xs
est généralement équivalent à List (x, xs)
.
Vous pouvez le faire avec d'autres classes de cas ayant des noms d'opérateur. Par exemple:
case class %%%(x: Int, y: Int)
a match {
case x %%% y => x + y
}
Comment l'expression de correspondance est-elle autorisée à être x :: xs plutôt que List (x, xs)?
Pour répondre à cette question:
Vu comme un motif , un infixe une opération telle que p op q est équivalente sur op (p, q) . C'est-à-dire l'infix opérateur op est traité comme un modèle de constructeur .
(Programmer en Scala, 1re éd., p. 331)
Voir aussi les questions sur les cas-clés scala