2010-08-13 18 views
36

निम्नलिखित स्काला मामले वर्ग पर विचार करें:बड़े स्कैला केस कक्षाओं से पैटर्न कैसे पैटर्न करें?

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

पैटर्न मिलान मुझे अनुमति देता है एक क्षेत्र को निकालने और दूसरों को छोड़ दे, तो जैसे करने के लिए:

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

मैं करना चाहते हैं क्या है, और क्या अधिक प्रासंगिक है जब है एक केस क्लास में ~ 20 विषम फ़ील्ड हैं, केवल कुछ मानों को निकालने के लिए है जिसमें WideLoad(_, _, _, _, _, some, _, _, _, thing, _, _, interesting) टाइपिंग शामिल नहीं है। , कई _, _, _, _

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

कोई आशा यहाँ है, या मैं टाइपिंग बाहर कई अटक कर रहा हूँ:

मुझे उम्मीद थी नामित आर्ग यहाँ मदद कर सकता है, हालांकि निम्न सिंटैक्स काम नहीं करता है?

संपादित: मैं समझता हूँ कि मैं case wl @ WideLoad(...whatever...) => wl.d कर सकते हैं, फिर भी मैं अभी भी सोच रहा हूँ भी terser वाक्यविन्यास लगा सकते हैं कि है कि क्या मैं एक अतिरिक्त val लागू करने के लिए बिना की जरूरत है।

+0

, सभी अंडरस्कोर यह बहुत पढ़ने के लिए कठिन बनाते हैं। एक नामित पैरामीटर सिंटैक्स पठनीयता को बहुत सुधार देगा, लेकिन जहां तक ​​मुझे पता है कि ऐसा कुछ भी मौजूद नहीं है। –

+0

मैं इस धारणा के तहत था कि सामान्य पैरामीटर सूचियां सामान्य रूप से बचने के लिए कुछ होती हैं। –

+0

आपका मतलब वाइडलोड (डी == डीएक्टर) –

उत्तर

34

अगर यह उचित है मैं नहीं जानता, लेकिन आप भी सिर्फ इतना है कि क्षेत्र, या क्षेत्रों के उस सेट (अपरीक्षित कोड) मैच के लिए एक वस्तु का निर्माण कर सकते हैं:

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

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

या यहाँ तक कि

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

someVal match { 
    case WideLoadBnD(b, d) => d ! SomeMessage(b) 
} 
यहां तक ​​कि 4 या 5 क्षेत्रों के साथ
+0

मुझे आपका विचार बहुत पसंद है। यह वही करता है जो मुझे थोड़ा अतिरिक्त वाक्यविन्यास, और स्पष्ट रूप से परिभाषित मंशा, टाइप सुरक्षा, इत्यादि के साथ करता है। यह तब तक एक महान स्टॉप गैप समाधान है जब मैंने इस कोड को छोटे केस वर्गों के लिए दोबारा प्रतिक्रिया दी है। –

15

आप हमेशा गार्ड पर वापस आ सकते हैं। यह :-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 

कहा कि मुझे लगता है कि आप अपने डिजाइन पर पुनर्विचार करना चाहिए वास्तव में अच्छा है, लेकिन आप राक्षस मामले कक्षाओं के लिए मिलान सामान्य पैटर्न की तुलना में बेहतर नहीं है। शायद आप केस क्लासेस, टुपल्स, सूचियों, सेट्स या मैप्स का उपयोग करके कुछ पैरामीटर को तार्किक रूप से समूहित कर सकते हैं। स्काला करता समर्थन नेस्ट पैटर्न मिलान:

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

हां, मैं उस लक्ष्य की ओर प्रतिक्रिया कर रहा हूं। मैंने अपने प्रश्न में प्रस्तावित रेत महलों के निर्माण से ऐसा करना आसान हो सकता है। –

संबंधित मुद्दे