2012-06-28 9 views
7

Tôi đang cố gắng viết một trình trích xuất để sử dụng trong việc khớp với một trường hợp nhiều tham số. Ví dụ đơn giản:Scala - extractor unapply confused

case class X(p1: String, p2: Int) 

Tôi muốn mỗi đối tượng trình trích xuất xác định giá trị cố định cho p1 và p2 được xác định khi sử dụng. (A, B, vv có thể không phải là một lớp trường và lớp con X, và tôi cũng muốn sử dụng X (,) như là một trường hợp) Ví dụ với áp dụng phương pháp:

object A { 
    def apply(p2: Int): X = X("A", p2) 
} 

object B { 
    def apply(p2: Int): X = X("B", p2) 
} 

... 

Đối với mô hình kết hợp, tôi muốn họ để phù hợp như thế này:

X("A", 2) match { 
    case A(2) => true // <- should match: p1="A" and p2=2 
    case A(_) => true // <- should match: p1="A" and p2=_ 
    case X("A", _) => true // <- should match: p1="A" and p2=_ 
    case A(1) => false // <- should not match 
    case B(2) => false // <- should not match: p1="B" and p2=2 
} 

tôi biết tôi cần phải xác định unapply phương pháp trong A, B, vv, nhưng tôi hoàn toàn bối rối gì chữ ký và logic nên là:

object A { 
    def unapply(x: ???): Option[???] = { 
    ??? 
    } 
} 

Hỗ trợ, vui lòng?

Trả lời

14

unapply lấy một ô bất kỳ và trả lại Option bất kỳ thứ gì bạn muốn trích xuất. Trong trường hợp của bạn này sẽ là:

scala> case class X(p1: String, p2: Int) 
defined class X 

scala> object A { 
    | def unapply(target: Any): Option[Int] = 
    |  PartialFunction.condOpt(target) { 
    |  case X("A", p2) => p2 
    |  } 
    | } 
defined module A 

scala> val A(x) = X("A", 1) 
x: Int = 1 

scala> val A(x) = X("B", 1) 
scala.MatchError: X(B,1) (of class X) 
... 

Nhưng phải trung thực, ví dụ bạn đưa ra có thể được viết lại mà không AB:

X("A",2) match { 
    case X("A", 2) => true 
    case X("A", 1) => false 
    case X("A", _) => true 
    case X("B", 2) => false 
} 
+5

Trong ví dụ đầu tiên, tôi thường sử dụng 'PartialFunction. condOpt' để tránh ghi lại trường hợp mặc định của một trường hợp không đúng (ở đây: 'PartialFunction.condOpt (target) {case X (" A ", p2) => Một số (p2)}'; bạn cũng có thể nhập 'PartialFunction._'). – Nicolas

+0

Tôi không biết điều đó. Tuyệt vời! –

+0

Thật đơn giản! Cảm ơn! BTW Tôi biết ví dụ này có thể được viết như thế, nhưng ví dụ này được đơn giản hóa. Mục đích chính của các vắt là để gói gọn các kết hợp tham số mà không dễ nhớ lại. – 7zark7