2012-11-28 20 views
5

मैं एक नए प्रकार, चंक को लागू करने की कोशिश कर रहा हूं, जो एक मानचित्र के समान है। असल में, एक "चंक" या तो स्ट्रिंग -> चंक, या एक स्ट्रिंग से मैपिंग है।स्कैला कस्टम मानचित्र

जैसे इसे इस तरह काम करने के लिए सक्षम होना चाहिए:

val m = new Chunk("some sort of value") // value chunk 
assert(m.getValue == "some sort of value") 

val n = new Chunk("key" -> new Chunk("value"), // nested chunks 
        "key2" -> new Chunk("value2")) 
assert(n("key").getValue == "value") 
assert(n("key2").getValue == "value2") 

मैं यह ज्यादातर, काम, सिवाय इसके कि मैं एक छोटे से कैसे + ऑपरेटर अपरिवर्तनीय नक्शे के लिए काम करता है द्वारा उलझन में हूँ।

class Chunk(_map: Map[String, Chunk], _value: Option[String]) extends Map[String, Chunk] { 
    def this(items: (String, Chunk)*) = this(items.toMap, None) 
    def this(k: String) = this(new HashMap[String, Chunk], Option(k)) 
    def this(m: Map[String, Chunk]) = this(m, None) 

    def +[B1 >: Chunk](kv: (String, B1)) = throw new Exception(":(do not know how to make this work") 
    def -(k: String) = new Chunk(_map - k, _value) 
    def get(k: String) = _map.get(k) 
    def iterator = _map.iterator 

    def getValue = _value.get 
    def hasValue = _value.isDefined 

    override def toString() = { 
    if (hasValue) getValue 
    else "Chunk(" + (for ((k, v) <- this) yield k + " -> " + v.toString).mkString(", ") + ")" 
    } 

    def serialize: String = { 
    if (hasValue) getValue 
    else "{" + (for ((k, v) <- this) yield k + "=" + v.serialize).mkString("|") + "}" 
    } 
} 

object main extends App { 
    val m = new Chunk("message_info" -> new Chunk("message_type" -> new Chunk("boom"))) 
    val n = m + ("c" -> new Chunk("boom2")) 
} 

इसके अलावा, सामान्य रूप में इस कार्यान्वयन उचित है, इस पर टिप्पणी की सराहना की जाएगी:

यहाँ मैं अब है।

धन्यवाद!

संपादित करें: बीजगणितीय डेटा प्रकार समाधान उत्कृष्ट है, लेकिन एक मुद्दा बनी हुई है।

def +[B1 >: Chunk](kv: (String, B1)) = Chunk(m + kv) // compiler hates this 
def -(k: String) = Chunk(m - k) // compiler is pretty satisfied with this 

- ऑपरेटर यहाँ काम करने लगता है, लेकिन + ऑपरेटर वास्तव में टाइप बी 1 (मुझे लगता है कि) के बारे में कुछ वापस जाने के लिए मुझे चाहता है? यह निम्न समस्या के साथ विफल:

overloaded method value apply with alternatives: (map: Map[String,Chunk])MapChunk <and> (elems: (String, Chunk)*)MapChunk cannot be applied to (scala.collection.immutable.Map[String,B1]) 

EDIT2: Xiefei इस सवाल का जवाब - नक्शा विस्तार की आवश्यकता है कि मैं हिस्सा के एक महाप्रकार (बी 1) के साथ + संभाल, इसलिए क्रम में यह करने के लिए मैं करना होगा उस के लिए कुछ कार्यान्वयन, तो यह पर्याप्त होगा:

def +[B1 >: Chunk](kv: (String, B1)) = m + kv 

हालांकि, मैं कभी सच, उपयोग करने के लिए है कि एक इरादा नहीं है बजाय, मैं भी मेरी कार्यान्वयन कि एक हिस्सा देता है इस प्रकार में शामिल होंगे:

def +(kv: (String, Chunk)):Chunk = Chunk(m + kv) 
+0

अपरिवर्तनीय मानचित्र के मामले में '+' के लिए कार्यान्वयन, अतिरिक्त कुंजी/मूल्य के साथ एक नया मानचित्र वापस करना होगा, है ना? आप पहले से ही एक मानचित्र ('_map') 'लपेटें' हैं, इसलिए आपके' + 'के कार्यान्वयन के लिए, बस '_map' पर प्रतिनिधि होगा:' def + [B1>: Chunk] (kv: (स्ट्रिंग, बी 1)) = _map + केवी'। असली मुद्दा यह है कि इससे 'सरल' चंक की (जो केवल एक स्ट्रिंग हैं) के लिए कोई समझ नहीं आता है। दूसरे शब्दों में, ऊपर दिए गए कन्स्ट्रक्टरों का सेट होने पर, ** और ** '+' को लागू करने से आपकी '' चंक' की परिभाषा टूट जाती है ... क्योंकि यह स्ट्रिंग-चंक को // // // // हिस्सा। – Faiz

उत्तर

1

क्या आपने विरासत के बजाय संरचना का उपयोग करने पर विचार किया है? तो, चंक के बजाय मानचित्र [स्ट्रिंग, चंक] को सीधे विस्तारित करने के बजाय, केवल चुंक को आंतरिक रूप से मानचित्र [स्ट्रिंग, चंक] का उदाहरण रखें और आपको आवश्यक अतिरिक्त विधियां प्रदान करें, और अन्यथा आंतरिक मानचित्र के तरीकों को प्रस्तुत करना।

+1

मैंने इस बारे में सोचा, और यह एक बहुत अच्छा मुद्दा है, हालांकि, मैं उन सभी उपहारों से मोहब्बत कर रहा था, जो मानचित्र को विस्तारित करके मुफ्त में शामिल हैं। – mattomatic

1
def +(kv: (String, Chunk)):Chunk = new Chunk(_map + kv, _value) 
override def +[B1 >: Chunk](kv: (String, B1)) = _map + kv 

आप क्या जरूरत है एक नया + तरीका है, और यह भी एक Map विशेषता में घोषित लागू।

2

जिस तरह से लिखा गया है, यह लागू करने का कोई तरीका नहीं है कि यह एक ही समय में Map और String दोनों नहीं हो सकता है। मैं Either का उपयोग कर मूल्य पर कब्जा करने और जो कुछ भी सुविधा विधियां जोड़ने पर विचार करना होगा की आवश्यकता:

case class Chunk(value:Either[Map[String,Chunk],String]) { 
    ... 
} 

कि भी क्या तुम सच में इस तरह के लिए एक मुख्य/मान जोड़े के रूप में जोड़ने की स्थिति में क्या करने की जरूरत के बारे में सोचना आप के लिए बाध्य करेगा एक Chunk जो String का प्रतिनिधित्व करता है।

5

Algebraic data type दृष्टिकोण के बारे में कैसे?

abstract sealed class Chunk 
    case class MChunk(elems: (String, Chunk)*) extends Chunk with Map[String,Chunk] { 
    val m = Map[String, Chunk](elems:_*) 
    def +[B1 >: Chunk](kv: (String, B1)) = m + kv 
    def -(k: String) = m - k 
    def iterator = m.iterator 
    def get(s: String) = m.get(s) 
    } 
    case class SChunk(s: String) extends Chunk 
    // A 'Companion' object that provides 'constructors' and extractors.. 
    object Chunk { 
    def apply(s: String) = SChunk(s) 
    def apply(elems: (String, Chunk)*) = MChunk(elems: _*) 
    // just a couple of ideas... 
    def unapply(sc: SChunk) = Option(sc).map(_.value) 
    def unapply(smc: (String, MChunk)) = smc match { 
     case (s, mc) => mc.get(s) 
    } 

    } 

कौन सा आप उपयोग कर सकते हैं: unapply एक्सट्रैक्टर्स

val simpleChunk = Chunk("a") 
val nestedChunk = Chunk("b" -> Chunk("B")) 
// Use extractors to get the values. 
val Chunk(s) = simpleChunk // s will be the String "a" 
val Chunk(c) = ("b" -> nestedChunk) // c will be a Chunk: Chunk("B") 
val Chunk(c) = ("x" -> nestedChunk) // will throw a match error, because there's no "x" 
// pattern matching: 
("x" -> mc) match { 
    case Chunk(w) => Some(w) 
    case _ => None 
} 

केवल एक सुझाव कर रहे हैं; उम्मीद है कि आप इस विचार के साथ गड़बड़ कर सकते हैं जब तक कि आप जो चाहते हैं उसे प्राप्त न करें।

+2

+1 फॉर्मूलेशन * "असल में, एक चंक स्ट्रिंग -> चंक, या एक स्ट्रिंग से मैपिंग है।" * इम्हो किसी प्रकार की सीलबंद अमूर्त कक्षा/विशेषता के लिए कॉल करता है। मेरे लिए खुला प्रश्न यह है कि इस सुपर क्लास में किस प्रकार की कार्यक्षमता शामिल की जानी चाहिए। क्या यह सामान्य रूप से मानचित्र या स्ट्रिंग की तरह व्यवहार करना चाहिए? इस संबंध में सवाल मुझे पूरी तरह से स्पष्ट नहीं है ... – bluenote10

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