2009-12-16 11 views
6

परिदृश्य: मैं एक आईएल पार्स कर रहा हूं और उदाहरण के लिए एक स्टैक्ड किए गए प्रतिनिधित्व से एक सीएफजी में परिवर्तित करना चाहता हूं।संग्रह में स्कैला केस क्लासेस

मेरी आईएल में पुशेंट (मूल्य), पॉप इत्यादि जैसे कई संचालन शामिल हैं। सवाल यह है कि अब स्केल के संदर्भ में कौन सा कार्यान्वयन सही होगा। मैं इतना है कि मैं के बाद से PushInt (1) PushInt के बराबर है कोड Alà

op match { 
    case PushInt(x) => doSomethingWith x 
    case Pop => ... 
} 

अब समस्या PushInt(1) :: PushInt(1) :: Pop :: Pop की तरह एक दृश्य के साथ मौजूद है लिख सकते हैं मामले वर्गों/वस्तुओं या एक्सट्रैक्टर्स उपयोग करने के लिए प्यार होता है (1) और मैं नहीं कर सकता एक संग्रह में एकाधिक (बराबर) संचालन जोड़ें। हालांकि मुझे पता है कि मैं कुछ जानकारी फेंक रहा हूं जो प्रवाह में स्थिति है, लेकिन यह अनुक्रम में टी इंडेक्स के रूप में निहित रूप से संग्रहीत है।

  • एक संभावित समाधान हैशकोड विधि को ओवरराइड करना और बराबर/हैशकोड के नियमों को तोड़ना है। मैं इसके साथ वास्तव में खुश नहीं हूँ।

  • एक अन्य विकल्प, एक "निर्माण के समय" प्रचार करता है जो सार आधार में संग्रहीत किया जाता है ताकि case class PushInt(value: Int) extends AbstractOp(AbstractOp.nextIndex)

  • उपयोग एक्सट्रैक्टर्स लेकिन इस मामले में मैं hashCode के कार्यान्वयन की तरह अच्छा सुविधाओं को याद करेंगे है के बराबर होती है, एक संपूर्ण मैच के लिए जांच और अधिक महत्वपूर्ण जांच।

तो मेरे सवाल का अब मेरी आवश्यकताओं के अनुसार मेरी संरचना मॉडल कैसे है। स्कैला के मामले में संभावित समाधानों में से कोई भी "सही" है?

+1

आप संग्रह में एकाधिक बराबर संचालन नहीं जोड़ सकते हैं? क्या यह मामला केवल तभी संग्रह है जब संग्रह एक सेट है? –

+1

नहीं, और अनुक्रम में अनुक्रमणिका के लिए पूछना भी बदतर है। ऑब्जेक्ट बराबर होने पर निश्चित रूप से सही कौन सा है। –

+1

आप निश्चित रूप से सूची में समान तत्वों को दोहरा सकते हैं। –

उत्तर

5

सबसे पहले, के सटीक उदाहरण आप को ढूँढने की समस्या से निबटने के लिए स्वतंत्र महसूस करते हैं पाया haven`t हैं:

scala> trait AbstractOp 
defined trait AbstractOp 

scala> case class Pop() extends AbstractOp { 
    | override def equals(other: Any) = other match { 
    |  case that: Pop => this eq that 
    |  case _ => false 
    | } 
    | } 
defined class Pop 

scala> case class PushInt(val i: Int) extends AbstractOp { 
    | override def equals(other: Any) = other match { 
    |  case that: PushInt => this eq that 
    |  case _ => false 
    | } 
    | } 
defined class PushInt 

scala> val l = List(PushInt(1), PushInt(1), Pop(), Pop()) 
l: List[Product with AbstractOp] = List(PushInt(1), PushInt(1), Pop(), Pop()) 

scala> val op = l(1) 
op: Product with AbstractOp = PushInt(1) 

scala> println(l.indexOf(op)) 
1 

यही कारण है, जाहिर है, इसका मतलब यह PushInt(1) != PushInt(1), जब तक यह PushInt(1) की ठीक उसी उदाहरण है। यह equals/hashCode अनुबंध तोड़ता नहीं है क्योंकि a.equals(b) => a.hashCode == b.hashCode, लेकिन a.hashCode == b.hashCode कुछ भी इंगित नहीं करता है।लेकिन अगर अपने ही उपयोग खोजने कि उदाहरण है, ऐसा करें:

scala> case class Pop() extends AbstractOp 
defined class Pop 

scala> case class PushInt(val i: Int) extends AbstractOp 
defined class PushInt 

scala> val l = List(PushInt(1), PushInt(1), Pop(), Pop()) 
l: List[Product with AbstractOp] = List(PushInt(1), PushInt(1), Pop(), Pop()) 

scala> val op = l(1) 
op: Product with AbstractOp = PushInt(1) 

scala> println(l.findIndexOf(op eq _)) 
1 

किसी भी तरह से, यदि आप सूची आप मुसीबत में होगा कि उदाहरण डालें। आपको यह सुनिश्चित करना होगा कि आपके द्वारा डाले गए प्रत्येक उदाहरण अद्वितीय हैं। यदि आप बार-बार उदाहरण डाला जाता है, या किसी भी आवृत्ति की प्रतिलिपि बनाते हैं, तो आप अपना स्वयं का संग्रह भी लिख सकते हैं, या स्काला 2.8 पर copy विधि के साथ आसान है।

+0

डैनियल, मैपिंग समस्या के बारे में क्या होगा यदि मैं आपके दूसरे सुझाव का उपयोग करूंगा? मुझे लगता है कि यह काम नहीं करता है, इसलिए मुझे शायद बराबर बराबर होना चाहिए, है ना? –

+0

क्या मैपिंग समस्या है? _ (पैट्रिक पढ़ता है) _ ओह, ठीक है। हाँ, वह है। उस स्थिति में, आप 'बराबर' ओवरराइड कर सकते हैं और उन समय के लिए वैकल्पिक तुलना ऑपरेटर बना सकते हैं जिन्हें आप 'पुश (1) == पुश (1) 'चाहते हैं। उदाहरण के लिए, '= ~ =' जैसी कुछ। –

+0

पहले समाधान के लिए, कृपया ध्यान दें कि आपको उस प्रकार के प्रकार की जांच करने की आवश्यकता नहीं है जिसे आप बाद में पहचान की जांच करेंगे। इसलिए यह पर्याप्त है: ओवरराइड def बराबर (अन्य: कोई भी) = यह eq अन्य – Blaisorblade

2

Joa कोई आपत्ति नहीं है;) ऐसे ही एक कोड की कल्पना कीजिए: आप:

trait AbstractOp 
case class Pop() extends AbstractOp 
case class PushInt(val i:Int) extends AbstractOp 

अब हम एक कार्यक्रम निर्देश के अनुक्रम का प्रतिनिधित्व

val l=List(PushInt(1), PushInt(1), Pop(), Pop()) 

सबसे पहले समस्या सूची का निर्माण एक ऑपरेशन की अनुक्रमणिका प्राप्त करना चाहते हैं

val op=l(1) // get the second operation for example 
// now you want to get back the index for the op you are using 
println(l.indexOf(op1)) // you will get 0 and not 1 

दूसरी समस्या: आप प्रत्येक ऑपरेशन को पिछली सूची से किसी मान पर मैप करना चाहते हैं, यह असफल हो जाएगा क्योंकि बराबर दो पॉप, या दो पुशेंट को अलग नहीं करेगा।

पीएस बेशक यह एक जवाब नहीं है, मैं कैसे दूसरों को टिप्पणी के तहत इस पोस्ट करने के लिए सही जगह पर ले जाने के लिए

+0

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

+0

पैट्रिक ने आवश्यकताओं को बहुत अच्छी तरह से समझाया है। धन्यवाद! –

+0

मैंने समान समस्याओं का उल्लेख करने के लिए दूसरी समस्याओं को दोहराया()। एक हैश मैप में एक ही हैश-कोड के साथ विभिन्न ऑब्जेक्ट्स डालने केवल एक प्रदर्शन समस्या है। – Blaisorblade

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