2011-11-26 7 views

Respuesta

26

Sin entrar en detalles y simplificar un poco:

Para los parámetros regulares apply construye y unapply de-estructuras:

object S { 
    def apply(a: A):S = ... // makes a S from an A 
    def unapply(s: S): Option[A] = ... // retrieve the A from the S 
} 
val s = S(a) 
s match { case S(a) => a } 

Para los parámetros repetidos, apply construye y unapplySeq de-estructuras:

object M { 
    def apply(a: A*): M = ......... // makes a M from an As. 
    def unapplySeq(m: M): Option[Seq[A]] = ... // retrieve the As from the M 
} 
val m = M(a1, a2, a3) 
m match { case M(a1, a2, a3) => ... } 
m match { case M(a, as @ _*) => ... } 

Tenga en cuenta que en ese segundo caso, los parámetros repetidos se tratan como un Seq y la similitud entre A* y _*.

Así que si quiere des-estructurar algo que naturalmente contiene varios valores individuales, use unapply. Si desea desestructurar algo que contiene un Seq, use unapplySeq.

18

Ariadia fija vs. variable arity. Pattern Matching in Scala (pdf) lo explica bien, con ejemplos de duplicación. También tengo ejemplos de duplicación en this answer.

Brevemente:

object Sorted { 
    def unapply(xs: Seq[Int]) = 
    if (xs == xs.sortWith(_ < _)) Some(xs) else None 
} 

object SortedSeq { 
    def unapplySeq(xs: Seq[Int]) = 
    if (xs == xs.sortWith(_ < _)) Some(xs) else None 
} 

scala> List(1,2,3,4) match { case Sorted(xs) => xs } 
res0: Seq[Int] = List(1, 2, 3, 4) 
scala> List(1,2,3,4) match { case SortedSeq(a, b, c, d) => List(a, b, c, d) } 
res1: List[Int] = List(1, 2, 3, 4) 
scala> List(1) match { case SortedSeq(a) => a } 
res2: Int = 1 

Así que, ¿cuál crees que se exhibe en el siguiente ejemplo?

scala> List(1) match { case List(x) => x } 
res3: Int = 1 
+0

¡Ah, gracias! Eso tiene sentido. Viniendo desde la perspectiva de Haskell, pienso en emparejar en 'List (a, b, c)' como desugaring en una coincidencia en 'a :: b :: c :: Nil', pero parece que Scala no hace esto; en su lugar, usa el método 'unapplySeq' de' List'. –

+0

El documento al que se hace referencia en esta respuesta se puede encontrar aquí: http://www.michaelrueegg.name/static/papers/PatternMatchingInScala.pdf –

+1

@dan Scala puede coincidir en las listas de la manera que espera, al tener un método de aplicación en el: : objeto acompañante. Como era de esperar, esta aplicación simplemente destruye la Lista (o más bien a :) en la cabeza y la cola. Tenga en cuenta que esto funciona solo para listas, no para ninguna secuencia. –

Cuestiones relacionadas