type parameter generic for comprehension scala pattern-matching unapply

scala - parameter - ¿Cuál es la diferencia entre unapply y unapplySeq?



scala generic (2)

¿Por qué Scala tiene tanto una unapply como una unapplySeq ? ¿Cuál es la diferencia entre los dos? ¿Cuándo debería preferir uno sobre el otro?


Arity fijo vs. arity variable. Pattern Matching en Scala (pdf) lo explica bien, con ejemplos de duplicación. También tengo ejemplos de reflejo en esta respuesta .

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

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

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


Sin entrar en detalles y simplificar un poco:

Para los parámetros regulares, apply constructs y unapply 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 constructs y unapplySeq las estructuras de unapplySeq :

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 _* .

Por lo tanto, si desea unapply algo que, naturalmente, contiene varios valores individuales, use "no unapply . Si desea unapplySeq algo que contiene un Seq , use unapplySeq .