2012-06-28 12 views
7

Sto tentando di scrivere un extractor (s) per l'utilizzo in corrispondenza di una classe di casi con più parametri. esempio semplificato:Scala - extractor unpply confusion

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

mi piacerebbe ogni oggetti estrattore per definire un valore fisso per p1, p2 ed è definita in uso. (A, B, ecc può non essere una classe case e sottoclasse X, e vorrebbe anche utilizzare X (,) come caso) Esempio con metodo apply:

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

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

... 

Per pattern matching, I vorrebbe loro di corrispondere in questo modo:

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 
} 

so che ho bisogno di definire unapply metodo A, B, ecc, ma io sono completamente confuso ciò che la firma e la logica dovrebbe essere:

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

Assistenza, per favore?

risposta

14

unapply accetta un Qualsiasi e restituisce un Option di ciò che si desidera estrarre. Nel tuo caso questo sarebbe:

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) 
... 

Ma ad essere onesti, l'esempio si avvicinò con potrebbe essere riscritto senza A e B:

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

Nel primo esempio, io uso spesso 'funzione parziale. condOpt'per evitare di scrivere il caso predefinito di un unlyly (qui: 'PartialFunction.condOpt (target) {case X (" A ", p2) => Some (p2)}'; puoi anche importare 'PartialFunction._'). – Nicolas

+0

Non lo sapevo. Eccezionale! –

+0

Così semplice! Grazie! A proposito, so che questo esempio potrebbe essere scritto così, ma questo esempio è semplificato. Lo scopo principale degli estrattori è incapsulare combinazioni di parametri che non sono facilmente richiamabili. – 7zark7