2011-11-26 7 views

Odpowiedz

26

Nie wdając się w szczegóły i upraszczając trochę:

Dla stałych parametrów apply buduje i unapply de-struktur:

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 } 

przypadku wielokrotnego parametrów apply buduje i unapplySeq de-struktur:

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 @ _*) => ... } 

Należy zauważyć, że w tym drugim przypadku powtarzające się parametry są traktowane jak Seq i podobieństwo między A* i _*.

Więc jeśli chcesz zdekantować coś, co naturalnie zawiera różne pojedyncze wartości, użyj unapply. Jeśli chcesz zdeformować coś zawierającego Seq, użyj unapplySeq.

18

Fixed-arity vs. variable arity. Pattern Matching in Scala (pdf) wyjaśnia to dobrze, z przykładami dublowania. Mam również przykłady dublowania w this answer.

skrócie:

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 

Więc, co myślisz jest eksponowana w poniższym przykładzie?

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

Ah dzięki! To ma sens. Wychodząc z perspektywy Haskella, myślę o dopasowaniu na "Liście (a, b, c)" jako pomijaniu w dopasowaniu na 'a :: b :: c :: Nil', ale wygląda na to, że Scala tego nie robi; zamiast tego używa metody 'unapplySeq'' List'. –

+0

Referat, o którym mowa w tej odpowiedzi, można znaleźć tutaj: http://www.michaelrueegg.name/static/papers/PatternMatchingInScala.pdf –

+1

@dan Scala można dopasować na listach w sposób zgodny z oczekiwaniami, stosując metodę unapply w: : obiekt towarzyszący. Zgodnie z oczekiwaniami, to unapply po prostu niszczy List (lub raczej: :) w głowę i ogon. Zauważ, że działa to tylko dla list, a nie dla żadnego seq. –

Powiązane problemy