2010-08-13 14 views
36

Rozważmy następujący Scala klasę obudowy:Jak wzorzec pasuje do dużych klas przypadków Scala?

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

dopasowanie Wzór pozwala mi wydobyć jedno pole i wyrzucić innych, tak jak poniżej:

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

Co chciałbym zrobić, a co bardziej istotne, gdy klasa case ma ~ 20 pól nieparzystych, jest wyodrębnianie tylko kilku wartości w sposób, który nie wymaga wpisywania WideLoad(_, _, _, _, _, some, _, _, _, thing, _, _, interesting).

miałem nadzieję, że może pomóc args nazwane tutaj, chociaż następującej składni nie działa:

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

Czy jest jakaś nadzieja tutaj, albo ja zatrzymany wpisywanie się wiele, wiele _, _, _, _?

EDIT: Rozumiem, że mogę zrobić case wl @ WideLoad(...whatever...) => wl.d, ale wciąż zastanawiam się, czy nie ma nawet terser składnia, że ​​robi to, co trzeba bez konieczności stosowania dodatkowego val.

+0

nawet z 4 lub 5 pól, wszystkie podkreślenia sprawiają, że bardzo trudne do odczytania. Składnia nazwanego parametru znacznie poprawiłaby czytelność, ale o ile wiem, nic takiego jeszcze nie istnieje. –

+0

Miałem wrażenie, że długie listy parametrów są czymś, czego należy unikać. –

+0

Ty miałeś na myśli sprawę WideLoad (d == dActor) –

Odpowiedz

34

nie wiem, czy to jest właściwe, ale można również zbudować obiekt pasuje tylko do tego pola lub że zestaw pól (kod niesprawdzone):

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

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

lub nawet

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

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

Bardzo lubię twój pomysł. Robi dokładnie to, czego potrzebuję, z niewielką dodatkową składnią i wyraźnie zdefiniowaną intencją, typem bezpieczeństwa itp. Jest to doskonałe rozwiązanie typu "stop-gap" do czasu, kiedy zreperymentowałem ten kod, aby mieć mniejsze klasy przypadków. –

15

Zawsze możesz wrócić do strażników. To naprawdę nie jest ładny, ale lepiej niż normalny wzór pasujący dla Ciebie klas przypadku potworów :-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 

To powiedział mi, że należy przemyśleć swój projekt. Prawdopodobnie możesz logicznie pogrupować niektóre parametry używając klas przypadków, krotek, list, zestawów lub map. Scala robi support zagnieżdżone dopasowanie Wzór:

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

Tak, jestem refactoring w kierunku tego celu. Może być łatwiej to zrobić, niż budować zamki z piasku podobne do tego, co zaproponowałem w moim pytaniu. –

Powiązane problemy