¿Por qué Scala tiene ambos unapply
y unapplySeq
? ¿Cuál es la diferencia entre los dos? ¿Cuándo debería preferir uno sobre el otro?¿Cuál es la diferencia entre unapply y unapplySeq?
33
A
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
Cuestiones relacionadas
- 1. ¿Cuál es la diferencia entre {0} y ""?
- 2. Cuál es la diferencia entre = y: =
- 3. ¿Cuál es la diferencia entre .ToString (+) y ""
- 4. Cuál es la diferencia entre $ (...) y `...`
- 5. ¿cuál es la diferencia entre:.! y: r !?
- 6. ¿Cuál es la diferencia entre ".equals" y "=="?
- 7. ¿Cuál es la diferencia entre dict() y {}?
- 8. ¿Cuál es la diferencia entre `##` y `hashCode`?
- 9. ¿Cuál es la diferencia entre "$^N" y "$ +"?
- 10. ¿Cuál es la diferencia entre [indefinido] y [,]?
- 11. ¿Cuál es la diferencia entre + = y = +?
- 12. ¿Cuál es la diferencia entre " " y ""?
- 13. Cuál es la diferencia entre $ y jQuery
- 14. OpenGL (ES) - ¿Cuál es la diferencia entre frustum y orto?
- 15. Cuál es la diferencia entre la función() {}() y la función() {}()
- 16. ¿Cuál es la diferencia entre la abstracción y la encapsulación?
- 17. ¿Cuál es la diferencia entre @ y $ y% en MSBuild?
- 18. ¿Cuál es la diferencia entre la vinculación estática y dinámica?
- 19. ¿Cuál es la diferencia entre la sección .got y .got.plt?
- 20. ¿Cuál es la diferencia entre el colado y la coerción?
- 21. ¿cuál es la diferencia entre el complemento y la biblioteca?
- 22. ¿Cuál es la diferencia entre el casting y la conversión?
- 23. ¿Cuál es la diferencia entre WPF y la aplicación Silverlight?
- 24. ¿Cuál es la diferencia entre uno mismo y la ventana?
- 25. ¿Cuál es la diferencia entre CookieContainer y la colección Response.Cookies?
- 26. ¿Cuál es la diferencia entre la relación Composición y Asociación?
- 27. ¿cuál es la diferencia entre el material y la textura?
- 28. ¿Cuál es la diferencia entre el marco y la arquitectura?
- 29. ¿Cuál es la diferencia entre la carpeta vim72 y vimfiles?
- 30. ¿cuál es la diferencia entre la lex y yacc
¡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'. –
El documento al que se hace referencia en esta respuesta se puede encontrar aquí: http://www.michaelrueegg.name/static/papers/PatternMatchingInScala.pdf –
@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. –