2009-10-05 12 views
8

Mam dwa pytania dotyczące klasy "::".Pytania dotyczące klas scala: pytania

:: może być stosowany jako

case head :: tail => ... 

Jak to działa? Co to jest dokładnie przepływ, którego używa Scala, aby dopasować instancję List do klasy :: case? Biorąc pod uwagę, że mam klasę MyClass, z op operator, mogę utworzyć klasę case o nazwie op, którą mogę użyć jako:

case foo op bar => .... 

?

+2

Duplikat strony http://stackoverflow.com/questions/1059145/how-is-this-case-class-match-pattern-working, naprawdę. –

+0

moje pytanie dotyczyło nie tylko tego, w jaki sposób come "::" znajduje się pomiędzy zmiennymi, ale także w jaki sposób klasa case może dopasować wystąpienia innej klasy (powodem jest to, że List # :: tworzy wystąpienia klasy :: case). – IttayD

Odpowiedz

5
 scala> abstract class Stack { 
    |  def push(n :Int):Stack 
    | } 
     defined class Stack 

    scala> final case class push(st :Stack,hd :Int) extends Stack { 
    |  override def push(n :Int):Stack = new push(this,n) 
    | } 
    defined class push 

    scala> object NullStack extends Stack { 
    |  override def push(n :Int):Stack = new push(null,n) 
    | } 
    defined module NullStack 

    scala> val s = NullStack.push(1).push(2) 
    s: Stack = push(push(null,1),2) 

    scala> def test(s :Stack) = s match { case st push i => println(st +"push " + i) } 
    test: (Stack)Unit 

    scala> test(s) 
    push(null,1)push 2 
+0

Świetna odpowiedź! więc sztuczka polega na tym, że List # :: zwraca instancję klasy case ::. – IttayD

3

To wyszczególnione na stronie 301 Programming in Scala, O wzór pasujący na List s.

The "cons" pattern x :: xs is a special case of an infix operation pattern. You know already that, when seen as an expression, an infix operation is equivalent to a method call. For patterns, the rules are different: When seen as a pattern, an infix operation such as p op q is equivalent to op(p, q) . That is, the infix operator op is treated as a constructor pattern. In particular, a cons pattern such as x :: xs is treated as ::(x, xs) . This hints that there should be a class named :: that correspond to the pattern constructor. Indeed there is such a class. It is named scala.:: and is exactly the class that builds non-empty lists.

2

W rzeczywistości fakt, że :: jest klasą przypadku, stanowi tylko połowę odpowiedzi. Powodem tego w dopasowywaniu wzorców jest to, że istnieje ekstraktor dla obiektu ::, który jest generowany automatycznie po zdefiniowaniu klasy przypadku. Dogodnie ::. Unapply zwraca listę, ponieważ :: extends List. Jeśli jednak chcesz użyć tej samej sztuczki dla list, nie można rozszerzyć listy, ponieważ jest to końcowa. Możesz zdefiniować obiekt za pomocą odpowiedniej metody anulowania, która ma oczekiwany podpis zwrotny. Na przykład, aby dopasować ostatni element listy można zrobić:

object ::> {def unapply[A] (l: List[A]) = Some((l.init, l.last))} 

List(1, 2, 3) match { 
    case _ ::> last => println(last) 
} 

(1 to 9).toList match { 
    case List(1, 2, 3, 4, 5, 6, 7, 8) ::> 9 => "woah!" 
} 
(1 to 9).toList match { 
    case List(1, 2, 3, 4, 5, 6, 7) ::> 8 ::> 9 => "w00t!" 
} 

ekstraktor musi powrócić opcja, która zawiera krotki dwóch Deconstructed elementów.

+0

Nie wydaje mi się, aby zastosowanie miało tutaj zastosowanie: scala> val l = Lista (1, 2, 3) l: Lista [Int] = Lista (1, 2, 3) scala> scala.::.unapply(l) : 6: błąd: niedopasowanie typu; znaleziono: Lista [Int] wymagane :: Val R = scala.::(1 Nil) R [?] :: [Int] = Lista (1) scala> scala ::,. unapply (r) res7: Some [List [Inti]] = Some (List()) , więc unapply działa tylko wtedy, gdy jest faktycznie skonstruowany przez klasę case, a nie dla ogólnej listy. – IttayD

+0

Nie ma nic szczególnego w tym, co się nie podoba, co tworzy klasa przypadku. Zauważ, że Lista jest abstrakcyjna i faktycznie każda niepusta lista jest instancją scala. :: Lista (1) .isInstanceOf [:: [Int.]] Co oznacza, że ​​to, co pasujesz we wzorach, to w rzeczywistości instancje of scala. :: (chyba, że ​​jest zero). Zauważ także, że jak tylko ponownie zdefiniujesz unapply dla ::, dopasowywanie do wzorca dla podzbiorów list: Obiekt :: {def unapply = false} – vdichev

0

Tekst cytowany przez eed3si9n znajduje się na stronie. 331 w edycji PDF "Programowanie w Scali" (1 wyd.)

Powiązane problemy