2012-06-28 11 views
7

Estoy intentando escribir un extractor (es) para usar en la comparación con una clase de caso de parámetros múltiples. ejemplo simplificado:Scala - extractor aplicar confusión

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

me gustaría cada objetos extractor para definir un valor fijo para p1 y p2 se define en el uso. (A, B, etc puede no ser una clase de caso y subclase X, y también le gustaría utilizar X (,) como un caso) Ejemplo con aplicar el método:

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

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

... 

Para coincidencia de patrones, I le gustaría para que coincidan con la siguiente manera:

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 
} 

sé que necesito para definir unapply método en el A, B, etc., pero estoy totalmente confundido lo que debe ser la firma y la lógica:

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

Asistencia, por favor?

Respuesta

14

unapply toma una Cualquiera y devuelve Option de lo que sea que desee extraer. En su caso esto sería:

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

Pero para ser honesto, el ejemplo que se le ocurrió podría reescribirse sin A y 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

En el primer ejemplo, a menudo uso 'función parcial. condOpt'para evitar escribir el caso predeterminado de una aplicación (aquí: 'PartialFunction.condOpt (target) {case X (" A ", p2) => Some (p2)}'; también puede importar 'PartialFunction._'). – Nicolas

+0

No lo sabía. ¡Increíble! –

+0

¡Tan simple! ¡Gracias! Por cierto, sé que este ejemplo podría escribirse así, pero este ejemplo está simplificado. El objetivo principal de los extractores es encapsular combinaciones de parámetros que no se recuperan fácilmente. – 7zark7