2010-08-13 15 views
36

Si consideri il seguente Scala caso classe:Come modellare le classi di case Scala di grandi dimensioni?

case class WideLoad(a: String, b: Int, c: Float, d: ActorRef, e: Date) 

pattern matching mi permette di estrarre un campo e scartare gli altri, in questo modo:

someVal match { 
    case WideLoad(_, _, _, d, _) => d ! SomeMessage(...) 
} 

Quello che mi piacerebbe fare, e ciò che è più rilevante quando una classe di case ha ~ 20 campi dispari, consiste nell'estrarre solo alcuni valori in un modo che non implichi la digitazione di WideLoad(_, _, _, _, _, some, _, _, _, thing, _, _, interesting).

Speravo che args nome potrebbe aiutare qui, anche se la sintassi seguente non funziona:

someVal match { 
    case WideLoad(d = dActor) => dActor ! SomeMessage(...) 
    //    ^---------- does not compile 
} 

C'è qualche speranza qui, o sono io bloccato digitando molti, molti _, _, _, _?

EDIT: capisco che posso fare case wl @ WideLoad(...whatever...) => wl.d, ma mi chiedo ancora se c'è sintassi anche terser che fa quello che mi serve senza dover introdurre un extra val.

+0

anche con 4 o 5 campi, tutte le sottolineature rendono piuttosto difficile da leggere. Una sintassi dei parametri con nome migliorerebbe molto la leggibilità, ma per quanto ne so non esiste ancora nulla del genere. –

+0

Ho avuto l'impressione che gli elenchi di parametri lunghi siano qualcosa da evitare in generale. –

+0

si intende caso WideLoad (d == dActor) –

risposta

34

Non so se questo è appropriato, ma si può anche costruire un oggetto solo per abbinare quel campo, o quella serie di campi (codice non testato):

object WideLoadActorRef { 
    def unapply(wl: WideLoad): Option[ActorRef] = { Some(wl.d) } 
} 

someVal match { 
    case WideLoadActorRef(d) => d ! someMessage 
} 

o anche

object WideLoadBnD { 
    def unapplySeq(wl: WideLoad): Option[(Int,ActorRef)] = { Some((wl.b,wl.d)) } 
} 

someVal match { 
    case WideLoadBnD(b, d) => d ! SomeMessage(b) 
} 
+0

Mi piace molto la tua idea. Fa esattamente quello di cui ho bisogno, con poca sintassi aggiuntiva, intento esplicitamente definito, sicurezza del tipo, ecc. È una soluzione di interruzione del lavoro eccezionale fino al momento in cui ho refactored questo codice per avere case class più piccole. –

15

È sempre possibile ricorrere alle guardie. Non è davvero bello, ma meglio di normale schema di corrispondenza per voi classi case mostro :-P

case class Foo(a:Int, b:Int, c:String, d:java.util.Date) 

def f(foo:Foo) = foo match { 
    case fo:Foo if fo.c == "X" => println("found") 
    case _ => println("arrgh!") 
} 

f(Foo(1,2,"C",new java.util.Date())) //--> arrgh! 
f(Foo(1,2,"X",new java.util.Date())) //--> found 

Detto questo penso che si dovrebbe ripensare il vostro disegno. Probabilmente è possibile raggruppare logicamente alcuni parametri usando case classes, tuple, liste, set o mappe. Scala fa supporto annidati pattern matching:

case class Bar(a: Int, b:String) 
case class Baz(c:java.util.Date, d:String) 
case class Foo(bar:Bar, baz:Baz) 

def f(foo:Foo) = foo match { 
    case Foo(Bar(1,_),Baz(_,"X")) => println("found") 
    case _ => println("arrgh!") 
} 

f(Foo(Bar(1,"c"),Baz(new java.util.Date, "X"))) //--> found 
f(Foo(Bar(1,"c"),Baz(new java.util.Date, "Y"))) //--> arrgh! 
+0

Sì, sto rifattando verso quell'obiettivo. Potrebbe essere più facile farlo se non costruire castelli di sabbia simili a quelli che ho proposto nella mia domanda. –

Problemi correlati