2009-10-05 29 views
8

Tôi có hai câu hỏi liên quan đến lớp 'case'.scala case classes questions

:: có thể được sử dụng như

case head :: tail => ... 

Làm thế nào nó hoạt động? Có nghĩa là, những gì chính xác là dòng chảy mà Scala sử dụng để phù hợp với một thể hiện danh sách với lớp :: trường hợp? Cho rằng tôi có một lớp MyClass, với toán tử op, tôi có thể tạo một trường hợp có tên là op mà tôi có thể sử dụng như:

case foo op bar => .... 

?

+2

Bản sao của http://stackoverflow.com/questions/1059145/how-is-this-case-class-match-pattern-working, có thật không. –

+0

câu hỏi của tôi không chỉ là làm thế nào đến '::' là giữa các biến, nhưng cũng như thế nào một trường hợp lớp có thể phù hợp với trường hợp của lớp khác (lý do là Danh sách # :: tạo trường hợp :: trường hợp lớp) – IttayD

Trả lời

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

câu trả lời tuyệt vời! do đó, mẹo là List # :: trả về một thể hiện của lớp case ::. – IttayD

3

Chi tiết được mô tả trong trang 301 của Programming in Scala, Giới thiệu mẫu phù hợp trên 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

Trên thực tế, thực tế là :: là trường hợp chỉ là một nửa câu trả lời. Lý do này hoạt động trong kết hợp mẫu là có một trình trích xuất cho đối tượng ::, được tạo tự động khi một lớp chữ hoa được xác định. Thuận tiện, ::. Unapply trả về một List, bởi vì :: extends List. Tuy nhiên, nếu bạn muốn sử dụng cùng một mẹo cho Danh sách, bạn sẽ không thể mở rộng Danh sách, bởi vì đó là final. Những gì bạn có thể làm là xác định một đối tượng với phương thức không thích hợp thích hợp, có chữ ký trả về dự kiến. Ví dụ, để phù hợp với yếu tố cuối cùng của một danh sách, bạn có thể làm:

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!" 
} 

Các vắt phải trả lại một lựa chọn, trong đó có một tuple của hai yếu tố deconstructed.

+0

Tôi không nghĩ rằng áp dụng không áp dụng ở đây scala> val l = Danh sách (1, 2, 3) l: Danh sách [Int] = Danh sách (1, 2, 3) scala> scala.::.unapply(l) : 6: lỗi: loại không phù hợp; Đã tìm thấy : Danh sách [Int] bắt buộc: :: [?] val r = scala.::(1, Nil) r: :: [Int] = Danh sách (1) scala> scala. ::. unapply (r) res7: Một số [Danh sách [Int]] = Một số (Danh sách()) vì vậy chỉ hoạt động không đúng khi thực sự được xây dựng bởi lớp chữ hoa, không phải cho danh sách chung. – IttayD

+0

Không có gì đặc biệt về trường hợp không thuận tiện mà một trường hợp tạo ra. Lưu ý rằng Danh sách là trừu tượng và thực sự bất kỳ danh sách không trống nào là một thể hiện của scala. :: Danh sách (1) .isInstanceOf [:: [Int]] Điều đó có nghĩa là những gì bạn đang khớp trong mẫu thực sự là trường hợp của scala. :: (trừ khi nó là Nil). Cũng lưu ý rằng ngay sau khi bạn chỉ xác định lại không phù hợp cho ::, đối sánh mẫu cho Danh sách ngắt: đối tượng :: {def unapply = false} – vdichev

0

Văn bản được trích dẫn bởi eed3si9n nằm trên trang p. 331 trong ấn bản PDF của "Lập trình trong Scala" (lần 1).