तेजी से बदलते डेटा के साथ विशुद्ध रूप से कार्यात्मक प्रोग्रामिंग भाषाएं कैसे व्यवहार करती हैं?


22

O (1) को हटाने और बदलने के लिए आप किन डेटा संरचनाओं का उपयोग कर सकते हैं? या जब आप कहा संरचनाओं की आवश्यकता है तो आप परिस्थितियों से कैसे बच सकते हैं?


2
हममें से जो विशुद्ध रूप से कार्यात्मक प्रोग्रामिंग भाषाओं से कम परिचित हैं, क्या आप पतले हैं तो आप थोड़ी अधिक पृष्ठभूमि प्रदान कर सकते हैं ताकि हम समझ सकें कि आपकी समस्या क्या है?
FrustratedWithFormsDesigner

4
@FrustratedWithFormsDesigner विशुद्ध रूप से कार्यात्मक प्रोग्रामिंग भाषाओं के लिए आवश्यक है कि सभी चर अपरिवर्तनीय हों, जिसके लिए "संशोधित" होने पर स्वयं के नए संस्करण बनाने वाली डेटा संरचनाओं की आवश्यकता होती है।
डोभाल

5
क्या आप विशुद्ध रूप से कार्यात्मक डेटा संरचनाओं पर ओकासाकी के काम के बारे में जानते हैं?

2
एक संभावना है कि उत्परिवर्तित डेटा के लिए एक मोनाड को परिभाषित करें (उदाहरण के लिए haskell.org/ghc/docs/4.08/set/sec-marray.html देखें )। इस तरह, परस्पर डेटा को IO के समान माना जाता है।
जियोर्जियो

1
@CodesInChaos: हालाँकि, ऐसी अपरिवर्तनीय संरचनाएँ आम तौर पर साधारण सरणियों की तुलना में बहुत अधिक ओवरहेड होती हैं। नतीजतन, वहाँ है बहुत ज्यादा एक व्यावहारिक अंतर। यही कारण है कि सामान्य प्रयोजन के प्रोग्रामिंग में लक्ष्य रखने वाली किसी भी विशुद्ध रूप से कार्यात्मक भाषा में, उत्परिवर्ती संरचनाओं का उपयोग करने का एक तरीका होना चाहिए, कुछ सुरक्षित तरीके से शुद्ध शब्दार्थ के साथ संगत। STहास्केल में इकाई इस उत्कृष्ट करता है।
लेफ्टरनैबाउट

जवाबों:


32

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

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

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

कार्यात्मक सेटिंग में उत्परिवर्तित अवस्था को सुरक्षित रूप से पेश करने का एक अन्य विकल्प STहास्केल में मोनाड है। इसे बिना म्यूटेशन के लागू किया जा सकता है और बैरिंग unsafe*फ़ंक्शंस में, यह ऐसा व्यवहार करता है जैसे कि यह केवल एक फैंसी रैपर था, जो लगातार डेटा संरचना को अव्यवस्थित रूप से गुज़ारता है (cf. State)। लेकिन कुछ प्रकार की प्रणाली चालबाजी के कारण जो मूल्यांकन के आदेश को लागू करता है और बचने से रोकता है, इसे सभी प्रदर्शन लाभ के साथ इन-प्लेस म्यूटेशन के साथ सुरक्षित रूप से लागू किया जा सकता है।


ज़िपर्स का उल्लेख करने के लायक भी हो सकता है जो आपको एक सूची या पेड़
जेके

1
@jk। वे थ्योरिटिकल कंप्यूटर साइंस पोस्ट मैं उल्लेख किया है में उल्लेख कर रहे हैं । इसके अलावा, वे कई प्रासंगिक डेटा संरचनाओं में से केवल एक (अच्छी तरह से, एक वर्ग) हैं और उन सभी पर चर्चा करना गुंजाइश से बाहर है और बहुत कम उपयोग है।

काफी उचित, लिंक का पालन नहीं किया था
जे.के.

9

एक सस्ता उत्परिवर्ती संरचना तर्क ढेर है।

विशिष्ट SICP शैली फैक्टरियल गणना पर एक नज़र डालें:

(defn fac (n accum) 
    (if (= n 1) 
        accum 
        (fac (- n 1) (* accum n)))

(defn factorial (n) (fac n 1))

जैसा कि आप देख सकते हैं, facतेजी से बदलते उत्पाद को समाहित करने के लिए दूसरे तर्क को एक उत्परिवर्तनीय संचायक के रूप में उपयोग किया जाता है n * (n-1) * (n-2) * ...। कोई भी परिवर्तनशील चर दृष्टि में नहीं है, हालांकि, और अनजाने में संचायक को बदलने का कोई तरीका नहीं है, उदाहरण के लिए दूसरे धागे से।

यह, एक सीमित उदाहरण है।

आप हेड नोड के सस्ते प्रतिस्थापन के साथ अपरिवर्तनीय लिंक प्राप्त कर सकते हैं (और सिर से शुरू होने वाले किसी भी भाग को विस्तार देकर): आप बस नए हेड पॉइंट को उसी अगले नोड पर बनाते हैं जैसे पुराने हेड ने किया था। यह कई सूची-प्रसंस्करण एल्गोरिदम (कुछ भी foldआधारित) के साथ अच्छी तरह से काम करता है ।

आप HAMTs पर आधारित सहयोगी सरणियों से बहुत अच्छा प्रदर्शन प्राप्त कर सकते हैं । तार्किक रूप से आप एक नया सहयोगी सरणी प्राप्त करते हैं जिसमें कुछ मुख्य-मूल्य जोड़ी (जोड़े) बदल गए हैं। कार्यान्वयन पुराने और नए बनाए गए ऑब्जेक्ट के बीच अधिकांश सामान्य डेटा साझा कर सकता है। हालांकि यह ओ (1) नहीं है; आमतौर पर आपको लॉगरिदमिक कुछ मिलता है, कम से कम सबसे खराब स्थिति में। दूसरी ओर, अपरिवर्तनीय पेड़, आमतौर पर उत्परिवर्तित पेड़ों की तुलना में किसी भी प्रदर्शन के दंड का शिकार नहीं होते हैं। बेशक, इसके लिए कुछ मेमोरी ओवरहेड की आवश्यकता होती है, आमतौर पर निषेधात्मक से दूर।

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

Clojure है यात्रियों कि परिवर्तनशील अपरिवर्तनीय डेटा संरचनाओं कि बाहर स्थानीय गुंजाइश रिसाव नहीं है की 'छाया' कर रहे हैं। कुछ समान हासिल करने के लिए क्लीन यूनिकिक्स का उपयोग करता है (यदि मुझे सही याद है)। जंग सांख्यिकीय रूप से जांचे गए अद्वितीय बिंदुओं के साथ समान कार्य करने में मदद करता है।


1
+1, क्लीन में अद्वितीय प्रकारों का उल्लेख करने के लिए भी।
जियोर्जियो

@ 9000 मुझे लगता है कि मैंने सुना है कि हस्केल के पास क्लोजर के ग्राहकों के समान कुछ है - अगर मैं गलत हूं तो कोई मुझे सही कर देगा।
पाऊल

@ अंपुल: मेरे पास हास्केल का बहुत ही सरसरी ज्ञान है, इसलिए यदि आप मेरी जानकारी (कम से कम गूगल पर एक कीवर्ड) प्रदान कर सकते हैं, तो मैं खुशी से उत्तर का संदर्भ शामिल करूंगा।
9000

1
@ अंपुल मुझे इतना यकीन नहीं है। लेकिन हास्केल के पास एमएल के समान कुछ बनाने refऔर उन्हें एक निश्चित दायरे में बांटने का एक तरीका है । देखें IORefया STRef। और फिर निश्चित रूप से TVars और MVars हैं जो समान हैं लेकिन sane समवर्ती शब्दार्थ के साथ ( TVars s और mutex MVars के लिए आधारित हैं )
डैनियल ग्रैज़र

2

आप जो पूछ रहे हैं वह थोड़ा बहुत व्यापक है। ओ (1) किस स्थिति से हटाने और प्रतिस्थापन? एक अनुक्रम के प्रमुख? पुंछ? एक मनमाना पद? उपयोग करने के लिए डेटा संरचना उन विवरणों पर निर्भर करती है। उस ने कहा, 2-3 फिंगर ट्रीज़ एक सबसे बहुमुखी लगातार डेटा संरचनाओं की तरह प्रतीत होते हैं:

हम 2-3 अंगुल वृक्षों को प्रस्तुत करते हैं, निरंतर स्थिर समय में सिरों तक पहुंच का समर्थन करने वाले लगातार अनुक्रमों का एक कार्यात्मक प्रतिनिधित्व, और छोटे टुकड़े के आकार में लघुगणक में समतल और विभाजन।

(...)

इसके अलावा, एक सामान्य रूप में विभाजन ऑपरेशन को परिभाषित करके, हम एक सामान्य उद्देश्य डेटा संरचना प्राप्त करते हैं जो अनुक्रम, प्राथमिकता कतार, खोज ट्री, प्राथमिकता खोज कतार और बहुत कुछ के रूप में काम कर सकता है।

आम तौर पर लगातार डेटा संरचनाओं में मनमाना पदों में फेरबदल करने पर लॉगरिदमिक प्रदर्शन होता है। यह एक समस्या हो सकती है या नहीं भी हो सकती है, क्योंकि O (1) एल्गोरिथ्म में निरंतरता अधिक हो सकती है, और लॉगरिदमिक मंदी एक धीमी समग्र एल्गोरिथ्म में "अवशोषित" हो सकती है।

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

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.