2012-04-13 17 views
19

मेरा वर्तमान उपयोग मामला बहुत छोटा है, या तो परिवर्तनीय या अपरिवर्तनीय मानचित्र चाल करेगा।स्कैला अपरिवर्तनीय मानचित्र, कब परिवर्तनीय जाना है?

एक विधि है कि एक अपरिवर्तनीय मानचित्र है, जो तब एक 3 पार्टी एपीआई विधि है कि अपरिवर्तनीय मानचित्र रूप में अच्छी तरह से लेता है कॉल लेता

def doFoo(foo: String = "default", params: Map[String, Any] = Map()) { 

    val newMap = 
    if(someCondition) params + ("foo" -> foo) else params 

    api.doSomething(newMap) 
} 

प्रश्न में मानचित्र आम तौर पर काफी छोटा हो जाएगा, अधिक से अधिक हो सकता है है केस क्लास उदाहरणों की एक एम्बेडेड सूची, कुछ हज़ार प्रविष्टियां अधिकतम। तो, फिर, इस मामले में अपरिवर्तनीय होने में थोड़ा प्रभाव डालें (यानी नए मैप वैल प्रति के माध्यम से मानचित्र के अनिवार्य रूप से 2 उदाहरण हैं)।

फिर भी, यह मुझे थोड़ी बातें सुनाती है, नक्शे को कॉपी बस कुछ ही k- के साथ एक नया नक्शा प्राप्त करने के लिए> v प्रविष्टियों यह पर हमला बोला।

मैं उन प्रविष्टियों के लिए उत्परिवर्तनीय और params.put("bar", bar) इत्यादि जा सकता हूं, और फिर params.toMap एपीआई कॉल के लिए अपरिवर्तनीय रूपांतरित करने के लिए, यह एक विकल्प है। लेकिन फिर मुझे म्यूटेबल मैप्स के आसपास आयात करना और पास करना है, जो स्कैला के डिफ़ॉल्ट अपरिवर्तनीय मानचित्र के साथ जाने की तुलना में परेशानी का थोड़ा सा है।

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

धन्यवाद

संपादित हां, तो ऐसा लगता है कि अपरिवर्तनीय नक्शे पर एक ऐड आपरेशन की पुष्टि, लगातार समय के पास ले जाता है @ DHG की और @ निकोलस के दावे कि एक पूरी कॉपी नहीं किया जाता है, जिसके लिए समस्या का हल ठोस मामला प्रस्तुत किया।

+4

देखें [चरम चतुरता: स्कैला में कार्यात्मक डेटा संरचनाएं] (http://www.infoq.com/presentations/ कार्यात्मक- डेटा- संरचना-in-Scala)। –

+0

धन्यवाद, अब इसे देख रहा है – virtualeyes

उत्तर

29

अपरिवर्तनीय मानचित्र कार्यान्वयन के आधार पर वास्तव में पूरे मूल नक्शा नकल नहीं हो सकता है कुछ प्रविष्टियों को जोड़ने। यह अपरिवर्तनीय डेटा संरचना दृष्टिकोण के फायदों में से एक है: स्कैला जितना संभव हो सके प्रतिलिपि बनाने के साथ दूर जाने का प्रयास करेगा।

व्यवहार इस तरह की एक List साथ देखने के लिए सबसे आसान है। अगर मेरे पास val a = List(1,2,3) है, तो वह सूची स्मृति में संग्रहीत है। हालांकि, अगर मैं val b = 0 :: a की तरह एक अतिरिक्त तत्व पहले जोड़ें, मैं एक नया 4-तत्व List वापस मिलता है , लेकिन स्काला नहीं orignal सूची a कॉपी किया था। इसके बजाए, हमने अभी एक नया लिंक बनाया है, जिसे इसे b कहा जाता है, और इसे मौजूदा सूची a पर पॉइंटर दिया।

साथ ही आप संग्रह के अन्य प्रकार के लिए इस तरह की रणनीतियों की कल्पना कर सकते हैं। उदाहरण के लिए, यदि मैं Map पर एक तत्व जोड़ता हूं, तो संग्रह केवल मौजूदा मानचित्र को लपेट सकता है, जब आवश्यक हो तो इसे वापस गिर सकता है, जबकि एपीआई प्रदान करते समय यह एक Map था।

+1

+1, ठंडा, एक गैर-मुद्दा तो अगर ऐसा है। मूल मानचित्र – virtualeyes

+0

पर केवल कुछ के-> v जोड़ने की आवश्यकता होने पर पूरी प्रतिलिपि बनाने के विचार से नाराज था, यह विस्तार करना दिलचस्प होगा कि अपरिवर्तनीय संग्रह अतिरिक्त के साथ अधिक मजबूत हैं और कौन से नहीं हैं। मैं ListMaps एक होने की उम्मीद करता हूं जो बहुत मजबूत नहीं होगा। –

5

DHG के जवाब देने के लिए इसके अलावा, आप performance of the scala collections को एक बार देख ले सकते हैं। यदि कोई ऐड/निकालना ऑपरेशन रैखिक समय नहीं लेता है, तो इसे केवल पूरी संरचना की प्रतिलिपि बनाने के अलावा कुछ और करना चाहिए। (ध्यान दें कि बातचीत सही नहीं है: यह नहीं है कि यह आपकी संरचना को प्रतिलिपि बनाने में रैखिक समय लेता है)

+0

+1, उत्कृष्ट लिंक, धन्यवाद। प्रदर्शन और लक्षणों के मुताबिक, अपरिवर्तनीय हैशैप पर एक ऐड ऑपरेशन निरंतर समय के करीब आता है, जो वर्तमान स्थिति में, जो मैं सुनना चाहता था, वह है ;-) – virtualeyes

14

एक परिवर्तनीय वस्तु का उपयोग करना अपने आप में बुरा नहीं है, यह एक कार्यात्मक प्रोग्रामिंग वातावरण में खराब हो जाता है, जहां आप कोशिश करते हैं कार्यों को शुद्ध और वस्तुओं को अपरिवर्तनीय रखकर साइड इफेक्ट्स से बचें।

हालांकि, यदि आप किसी फ़ंक्शन के अंदर एक म्यूटेबल ऑब्जेक्ट बनाते हैं और इस ऑब्जेक्ट को संशोधित करते हैं, तो फ़ंक्शन अभी भी शुद्ध है यदि आप फ़ंक्शन के बाहर इस ऑब्जेक्ट का संदर्भ जारी नहीं करते हैं।

def buildVector(x: Double, y: Double, z: Double): Vector[Double] = { 
    val ary = Array.ofDim[Double](3) 
    ary(0) = x 
    ary(1) = y 
    ary(2) = z 
    ary.toVector 
} 

अब, मुझे लगता है कि इस दृष्टिकोण से उपयोगी है/दो मामलों में सिफारिश की:: यह कोड की तरह है करने के लिए स्वीकार्य है (1) प्रदर्शन, बनाने और अपरिवर्तनीय वस्तु को संशोधित करता है, तो अपने पूरे आवेदन की एक टोंटी है; (2) कोड पठनीयता, क्योंकि कभी-कभी किसी जटिल ऑब्जेक्ट को स्थानांतरित करना आसान होता है (लेंस, ज़िप्पर, इत्यादि का उपयोग करने के बजाए)

+0

हां, अपरिवर्तनीय डिफ़ॉल्ट के साथ रहने का विकल्प एक परिवर्तनीय मानचित्र में गुज़र रहा था , फिर एपीआई कॉल करने से पहले अपरिवर्तनीय मानचित्र में परिवर्तित हो रहा है, इसलिए आपके डू-इट-ऑल-लोकल दृष्टिकोण से तुलनात्मक रूप से शुद्ध नहीं है। यह सामान्य, गैर-चरम मामले की तरह लगता है, अपरिवर्तनीय डिफ़ॉल्ट ठीक है। बेशक, मैं अभी भी अपरिवर्तनीय मानचित्र पर परिवर्तनीय मानचित्र के लिए ठोस उपयोग मामलों के रूप में अस्पष्ट नहीं हूं। मुझे मामूली मामला नहीं प्रदान करके दरवाजा खोलना चाहिए था जिससे मुझे सवाल पूछने का कारण बन गया ... – virtualeyes

+0

+1: यह मूल रूप से माइक्रोसॉफ्ट के बीसीएल अपरिवर्तनीय संग्रह (https: //www.nuget) द्वारा नियोजित "बिल्डर" पैटर्न है। संगठन/पैकेज/माइक्रोसॉफ्ट.बीसीएल। इमटेबल) .NET के लिए। –

0

मैं संग्रह पैरामीटर का उपयोग घोषित पैरामीटर प्रकारों (इनपुट या वापसी मूल्यों के रूप में करना चाहता हूं)) परिवर्तनीय या अपरिवर्तनीय नक्शे के बजाय। कलेक्शन मैप्स अपरिवर्तनीय इंटरफेस हैं जो दोनों प्रकार के कार्यान्वयन के लिए काम करते हैं। मानचित्र का उपयोग करने वाली उपभोक्ता विधि को वास्तव में मानचित्र कार्यान्वयन या इसे कैसे बनाया गया था, के बारे में जानने की आवश्यकता नहीं है। (वैसे भी यह वास्तव में इसके किसी भी व्यवसाय का नहीं है)।

यदि आप इसका उपयोग करने वाले उपभोक्ताओं से मानचित्र के विशेष निर्माण (इसे उत्परिवर्तनीय या अपरिवर्तनीय) छुपाए जाने के दृष्टिकोण के साथ जाते हैं तो आप अभी भी एक अनिवार्य रूप से अपरिवर्तनीय मानचित्र डाउनस्ट्रीम प्राप्त कर रहे हैं। और संग्रह का उपयोग करके। मैप एक अपरिवर्तनीय इंटरफेस के रूप में आप पूरी तरह से ".toMap" अक्षमता को हटा दें जो आपके पास अपरिवर्तनीय उपयोग करने के लिए लिखे गए उपभोक्ताओं के साथ होगा। मैप टाइप की गई वस्तुएं। एक पूरी तरह से निर्मित मानचित्र को दूसरे में परिवर्तित करने के लिए बस एक इंटरफेस का अनुपालन करने के लिए पहले व्यक्ति द्वारा समर्थित नहीं है, जब आप इसके बारे में सोचते हैं तो वास्तव में बिल्कुल अनावश्यक ओवरहेड होता है।

मुझे कुछ वर्षों में संदेह है कि हम इंटरफेस के तीन अलग-अलग सेट (म्यूटेबल मैप्स, अपरिवर्तनीय मानचित्र और संग्रह मानचित्र) पर वापस देखेंगे और महसूस करेंगे कि 99% समय केवल 2 की आवश्यकता है (mutable और संग्रह) और (दुर्भाग्यवश) डिफ़ॉल्ट अपरिवर्तनीय मानचित्र इंटरफ़ेस का उपयोग करके वास्तव में "स्केलेबल भाषा" के लिए बहुत अनावश्यक ओवरहेड जोड़ता है।

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