2011-09-01 2 views
13

non sembrano mescolare molto bene:caso, il pattern matching e costruttori al curry a Scala

abstract class A 
case class B (var a: Int)(var b: String) extends A 
case class C extends A 

Quanto segue non funziona:

B(1)("1") match { 
    case B(a)(b) => print("B") 
    case C() => print("C") 
} 

Il problema è che il pattern matching e gli argomenti al curry non sembrano funzionare. C'è un work-around per questo?

risposta

7

Cosa c'è di sbagliato in questo?

def m(a: A) = a match { 
    case b: B => print("B") 
    case c: C => print("C") 
} 

Sto solo chiedendo perché non hai chiesto più funzionalità di questo.

EDIT

Questo potrebbe aiutare:

object Dog { 
    def apply(name: String)(size: Int) = new Dog(name)(size) 
    def unapply(dog: Dog) = Some(dog.name, dog.size) 
} 
class Dog(val name: String)(var size: Int) 

Ora è possibile creare i cani sia così:

new Dog("Snoopy")(10) 

o come questo:

Dog("Snoopy")(10) 

Ma quando si esegue lo schema di corrispondenza sui cani, il modello di costruzione è non al curry.

Dog("Snoopy")(10) match { 
    case Dog(a, b) => // do sth with a or b 
} 
+0

Il tuo primo esempio funzionerebbe, ma non sarei in grado di accedere a B.a e B.b nell'istruzione case senza fare un brutto typecasting. Inoltre, nella tua modifica, non sono sicuro di capire perché il modello di costruzione non è al curry. È perché inapplicato? –

+0

A dire il vero non ho idea del perché funzioni. Sono inciampato su di esso attraverso prove ed errori. È certamente menzionato da qualche parte nelle specifiche di Scala. Potresti voler controllare se è pertinente nel tuo caso. – agilesteel

+1

Sì, lo schema che si utilizza in un'istruzione case è quello fornito dal risultato della funzione non valida. Non può mai essere curato. La sezione corrispondente nella scala specifica è il §8.1.8 – Nicolas

2

È possibile utilizzare una normale classe di casi e solo definire un metodo di fabbrica con più di un elenco di parametri.

+0

Si può aggiungere che il metodo di fabbrica non può essere calied 'apply' se è dichiarato nell'oggetto associato (poiché avrà la stessa cancellazione di e uno dichiarato grazie alla classe del caso). – Nicolas

11

Se si guarda alla firma della funzione unapply creato per la classe B, vedrete che si tratta: unapply(x$0: Q): Option[Int]. Pertanto, la funzione non applicabile funziona con il primo intervallo di parametri delle classi case.

È confermato dalla specifica scala (§5.3.2):

I parametri formali nella fi sezione primo parametro di una classe case sono chiamati elementi; sono trattati appositamente. Innanzitutto, il valore di come parametro può essere estratto come campo di un modello di costruzione.

Si afferma chiaramente che solo la prima sezione di parametro è disponibile tramite l'estrattore.

Diverse soluzioni:

  • uncurry i parametri
  • utilizzare un pattern matching con la guardia, se si desidera verificare i 2 valori: case [email protected](3) if x.b == "bazinga" => ...
  • utilizzare una classe normale e definire il proprio oggetto associato con il tuo proprio applicare/non applicabile