2012-10-29 14 views
8

Coursera इसे जारी रखते हुए स्काला पाठ्यक्रम, मार्टिन ओडर्स्की एक उदाहरण कोड है जो है पता चला:मैप ऑपरेशन के बाद एक रेंज को वेक्टर में क्यों बदल दिया गया है?

1 to 5 map (i => i*i) 

और उन्होंने कहा Range क्योंकि वे एक ही इंटरफ़ेस (IndexedSeq) का हिस्सा एक Vector में तब्दील हो जाता है और परिणाम प्रदर्शित नहीं किया जा सकता है Range के रूप में (यह इसके उदाहरण में अधिक स्पष्ट था क्योंकि उसने एक जोड़ी उत्पन्न की जो Range के रूप में प्रतिनिधित्व योग्य नहीं है)।

मुझे समझ में नहीं आ रहा है क्योंकि मुझे लगता है कि उसने पहले कहा था कि अभिव्यक्ति के लिए पहला जनरेटर इस तरह के तत्व को निर्धारित करेगा, जो कम से कम Range के लिए हमेशा सत्य नहीं लगता है।

और मैं क्यों उत्पादन Vector है, क्योंकि Vector केवल एक दूसरे कार्यान्वयन कि परिणाम से ऊपर अभिकलन प्रतिनिधित्व कर सकते हैं नहीं हो सकता है समझने के लिए यकीन नहीं है।

क्या कोई मुझे इस भाग को समझने में मदद कर सकता है?

उत्तर

9

map गिरा दिया चुपके से एक CanBuildFrom एक अंतर्निहित तर्क के रूप में लेता है। इसका काम एक नया संग्रह तैयार करना है जिसे आपने पहले ही प्राप्त किया है (और सामग्री का प्रकार)। चूंकि Range में मनमानी सामान नहीं हो सकते हैं - यहां तक ​​कि मनमानी पूर्णांक भी नहीं - CanBuildFrom कोई Range उत्पन्न करता है।Range का सबसे विशिष्ट सुपरटेप है जिसमें CanBuildFromIndexedSeq है। वास्तव में इस संग्रह द्वारा निर्मित संग्रह Vector है।

+1

तो क्या आपका मतलब है कि स्कैला डिफ़ॉल्ट रूप से कुछ अंतर्निहित CanBuildFroms द्वारा आयात करता है और मैं अंततः उन्हें या कुछ ओवरराइड कर सकता हूं? क्या यह संभव है, समझने के लिए, इस मामले में एक वेक्टर की तुलना में कुछ और उत्पादन करने के लिए? –

+1

@ सेबेस्टियन लॉर्बर - वास्तव में आप कर सकते हैं! 'ब्रेकऑट' की तलाश करें शायद इसे करने का सबसे सुविधाजनक तरीका अगर कुछ अन्य निहित पहले से लागू हो सकते हैं, उदा। http://stackoverflow.com/questions/2592024 –

+0

हां, यदि आप स्पष्ट रूप से एक वैध निर्माता प्रदान करते हैं तो आप – Arjan

1

VectorIndexedSeq के लिए डिफ़ॉल्ट कार्यान्वयन है। map को Range के रूप में प्रदर्शित नहीं किया जा सकता है क्योंकि Range कक्षा को संख्याओं की एक श्रृंखला शामिल करने के लिए डिज़ाइन किया गया है जिसे प्रारंभ, रोक और चरण मान (पाइथन में range के समान) द्वारा दर्शाया जा सकता है। एपीआई दस्तावेज़ निर्दिष्ट करते हैं कि यह IndexSeq का एक विशेष मामला है।

हम देख सकते हैं 1 to 5 map { i => i * i } हमें मूल्यों का एक कंटेनर मिलेगा (1, 4, 9, 16, 25)। हम एक स्टार्ट और स्टॉप प्राप्त कर सकते हैं, लेकिन कोई निरंतर चरण मूल्य नहीं है।

2

के रूप में मुझे यकीन है कि मार्टिन यह भी बताया हूँ, for comprehensions (में अनुवाद कर रहे हैं) श्रृंखलित map और flatMap तरीकों में से आमंत्रण के अनुरूप (और foreach अगर आप yield उपयोग न करें)।

कारण है कि यह आम तौर पर पहले जनरेटर के प्रकार के एक मूल्य में परिणाम है कि map और flatMap आम तौर पर एक ही प्रकार वापसी उनके रिसीवर (map एक List रिटर्न एक List पर, आदि) के रूप में है।

अब Range एस के साथ समस्या यह है कि वे उन चीजों का प्रतिनिधित्व नहीं कर सकते हैं जो पूर्णांक के नियमित अनुक्रम नहीं हैं। नतीजतन, map और flatMapas defined for Range का वापसी प्रकार Range नहीं हो सकता है। अगला सबसे अच्छा मैच Vector है, जो अनुक्रमित अनुक्रम का प्रोटोटाइपिकल कार्यान्वयन है।

(आप स्रोत कोड या यहाँ तक कि स्काला डॉक पेज मैं से जुड़ा हुआ को देखें, तो आपको लगता है कि यह है कि बस वापसी प्रकार है, लेकिन धारणात्मक, यही कारण है है एक छोटे से अधिक जटिल है देखेंगे संपादित करें।: ... और अब रेक्स केर सिर्फ CanBuildFrom बम।)

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