2013-01-19 33 views
5

स्कैला (2.10) में यदि मैं List(1.0, 2) मांगता हूं तो मुझे List[Double] मिलता है, जैसा कि अपेक्षित है।अप्रत्याशित स्कैला मानचित्र प्रकार

लेकिन ...

अगर मैं एक Map(1.0 -> 'A', 2 -> 'B') के लिए पूछना मैं एक Map[AnyVal, Char] मिलता है। मैं चाबियाँ Double टाइप करना चाहता हूं। Map[Double, Char](1.0 -> 'A', 2 -> 'B) के लिए पूछना '2' पर एक प्रकार का मेल नहीं खाता है।

यह मुझे सबसे भ्रमित लगता है! क्या यह असंगत नहीं है?

इसके अलावा:List[(Double, Char)]((1.0, 'A'), (2, 'B')).toMap मुझे एक नक्शा [डबल, चार] देता है।

+0

reproducable 2.9.2 के साथ-साथ। –

उत्तर

6

आप स्काला के type hierarchy पर गौर करते हैं, तो आपको लगता है कि आदिम प्रकार एक उप-प्रकार/सुपर-प्रकार संबंध में नहीं हैं देख सकते हैं। हालांकि, संख्यात्मक चौड़ाई नामक एक तंत्र है जो उदाहरण के लिए आपको कहने से Double तर्क लेने वाली विधि को कॉल करने की अनुमति देता है। Int फिर स्वचालित रूप से Double पर "विस्तृत" हो जाता है।

यही कारण है कि List(1.0, 2) आपको List[Double] देता है।

लेकिन Map कन्स्ट्रक्टर Tuple[A, B] तर्क लेता है। संख्यात्मक चौड़ाई उच्च क्रम प्रकारों पर लागू नहीं होती है, इसलिए यदि आप संख्यात्मक प्रकारों को मिश्रित करते हैं तो लक्ष्य प्रकार अनुमान आपके लिए काम नहीं करता है।

case class Test[A](tup: (A, Char)*) 
Test(1.0 -> 'A', 2 -> 'B') // AnyVal 

इसके अलावा, तीर ऑपरेटर -> अपने रास्ते में हो जाता है:

Test[Double](2 -> 'B') // found: (Int, Char) required: (Double, Char) 

इस प्रकार निष्कर्ष मुझे लगता है कि का एक और सीमा है। एक ट्यूपल a -> b लिखना (a, b) के लिए सिंटैक्टिक चीनी है, जो पर Predef पर अंतर्निहित विधि द्वारा प्रदान किया गया है।इस अविवेक के बिना, अगर आप Tuple2 सीधे निर्माण, यह काम करता है:

Test[Double]((2, 'B')) 

तो सांख्यिक चौड़ा अभी भी काम नहीं करता है, लेकिन कम से कम आप प्रकार लागू कर सकते हैं:

Map[Double, Char]((1.0, 'A'), (2, 'B')) 

एक अंतिम उदाहरण सांख्यिक चौड़ा काम कर दिखा:

def map[A, B](keys: A*)(values: B*) = Map((keys zip values): _*) 
map(1.0, 2)('A', 'B') // Map[Double, Char] 
3

किसी सूची के मामले में, एक प्रकार की घोषणा के बिना, स्कैला सभी तत्वों को देखता है और सामान्य प्रकार खोजने की कोशिश करता है। आपके मामले में, चूंकि इंट को डबल में परिवर्तित किया जा सकता है, इसलिए यह आपकी मिश्रित सूची को एक सूची [डबल] में परिवर्तित करता है जो आपके एक इंटेल को बढ़ावा देता है।

मानचित्र निर्माता 2-टुपल्स की एक श्रृंखला लेता है। तुम्हें पता है, समान व्यवहार प्राप्त करता है, तो आप सिर्फ tuples की एक सूची का निर्माण किया जाएगा:

scala> List((1, "one"), (2.0, "two.oh")) 
res0: List[(AnyVal, String)] = List((1,one), (2.0,two.oh)) 

Tuple2 [इंट, स्ट्रिंग] स्वचालित रूप से Tuple2 [डबल, स्ट्रिंग] करने के लिए प्रोत्साहित नहीं किया जा सकता। इस मामले में, आप एक प्रकार घोषणा के साथ एक सा बाहर संकलक मदद करने के लिए की आवश्यकता होगी:

scala> val x: List[(Double, String)] = List((1, "one"), (2.0, "two.oh")) 
x: List[(Double, String)] = List((1.0,one), (2.0,two.oh)) 

या

scala> val x = List[(Double, String)]((1, "one"), (2.0, "two.oh")) 
x: List[(Double, String)] = List((1.0,one), (2.0,two.oh)) 

या अपने मामले में:

scala> val x = List[(Double, String)]((1, "one"), (2.0, "two.oh")).toMap 
x: scala.collection.immutable.Map[Double,String] = Map(1.0 -> one, 2.0 -> two.oh) 

किसी कारण से , मानचित्र पर प्रकार की घोषणा का उपयोग कर काम नहीं करता है। सुनिश्चित नहीं हैं कि क्यों:

scala> val x = Map[Double, String](1 -> "one", 2.0 -> "two.oh") 
<console>:7: error: type mismatch; 
found : (Int, String) 
required: (Double, String) 
    val x = Map[Double, String](1 -> "one", 2.0 -> "two.oh")