2010-08-13 16 views
36

Aşağıdaki Scala vaka sınıfını göz önünde bulundurun:Büyük Scala vaka sınıfları nasıl eşleştirilir?

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

Desen eşleştirmesi bir alan açıp diğerlerini atmamı sağlar, örneğin:

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

Ne yapmak isterdim ve ne zaman daha alakalı vaka sınıfı ~ 20 tek alanları, WideLoad(_, _, _, _, _, some, _, _, _, thing, _, _, interesting) yazmayı içermeyen bir şekilde sadece birkaç değeri ayıklamaktır.

Aşağıdaki sözdizimi çalışmadığı halde, adlandırılmış hata kodlarının burada yardımcı olabileceğini umuyordum:

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

Burada herhangi bir umut var mı, yoksa çok fazla _, _, _, _ yazdım mı?

EDZ: case wl @ WideLoad(...whatever...) => wl.d yapabildiğimi anlıyorum, yine de ek bir val tanıtmak zorunda kalmadan ihtiyacım olan şeyleri bile yapan bir sözdizimi olup olmadığını merak ediyorum.

+0

, tüm alt çizgiler okumaya oldukça sert olun. Adlandırılmış bir parametre sözdizimi okunabilirliği çok artırır, ancak henüz böyle bir şey bilmediğim sürece. –

+0

Uzun parametre listelerinin genel olarak kaçınılması gereken bir şey olduğu izlenimindeydim. –

+0

kastediyorsunuz WideLoad (d == dActor) –

cevap

34

bu uygun olup olmadığını bilmiyorum, ama aynı zamanda sadece bu alanı veya alanları kümeyi (denenmemiş kodu) eşleştirmek için bir nesneyi inşa edebilirsiniz: Scala destek iç içe desen eşleştirme yapar

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

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

ya da 4 veya 5 alanlarla bile

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

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

Fikrinizi çok beğeniyorum. Tam olarak neye ihtiyacım var, biraz ekstra sözdizimi ve açıkça tanımlanmış niyet, tür güvenliği, vb. Bu kodu, daha küçük vaka sınıflarına sahip olacak şekilde yeniden kodlandırdığım zamana kadar harika bir durma çözümü. –

15

Korumalara her zaman geri dönebilirsiniz. Ben tasarımınızı yeniden düşünmek gerektiğini düşünüyorum söyledi

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 

:-P gerçekten güzel ama seni canavar vaka sınıflar için eşleşen normal seyrinden daha iyi değil. Muhtemelen bazı sınıfları vaka sınıfları, tupl'lar, listeler, kümeler veya haritalar kullanarak mantıklı bir şekilde gruplayabilirsiniz.

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

Evet, bu hedefe doğru refactoring yapıyorum. Bunu yapmak istediğim şeye benzeyen kumdan kaleler yapmaktan daha kolay olabilir. –

İlgili konular