कार्यात्मक प्रोग्रामिंग में राज्य की समस्याओं से निपटना


19

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


4
पहला कदम इस बात की संभावना है कि समस्याएँ स्वाभाविक रूप से नहीं हैं।
तेलस्टिन

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

4
डेटाबेस उदाहरण के लिए शायद छोड़कर, उन समस्याओं को स्वाभाविक रूप से राज्य नहीं कर रहे हैं । उदाहरण के लिए, GUI प्रोग्रामिंग के लिए, आप वास्तव में समय के खराब, अंतर्निहित मॉडल के रूप में परिवर्तनशील स्थिति का उपयोग कर रहे हैं ; कार्यात्मक प्रतिक्रियाशील प्रोग्रामिंग आपको उन घटनाओं की स्थिति प्रदान करने के बिना स्पष्ट रूप से मॉडल का समय देता है जो आप जोड़ सकते हैं।
तिखन जेल्विस

1
एक सरल उपाय है: जब आप एक ऐसी समस्या के लिए आते हैं जो आसानी से एफपी तकनीकों के साथ मॉडलिंग नहीं की जाती है , तो इसे हल करने के लिए कार्यात्मक प्रोग्रामिंग का उपयोग न करें। नौकरी के लिए सही उपकरण और वह सब ...
मेसन व्हीलर

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

जवाबों:


21

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

यहां मूल रणनीति यह है कि आप ऐसे कार्य बनाएं जो एक राज्य में ले जाएं और नया राज्य लौटाएं । तो एक कण सिम्युलेटर एक फ़ंक्शन होगा जो Setइनपुट के रूप में कणों का एक हिस्सा लेता है और Setएक समय कदम के बाद कणों का एक नया रिटर्न देता है । फिर आप बार-बार उस फ़ंक्शन को उसके पिछले परिणाम के इनपुट सेट के साथ कॉल करते हैं।


5
+1 एफपी में राज्य होना ठीक है, सिर्फ परस्पर राज्य नहीं ।
5

1
इस अंतर्दृष्टि के लिए धन्यवाद। अक्षमता के बारे में मेरी चिंताओं को @logc द्वारा विफल किया गया था; राज्य कैसे रूपांतरित होता है, इसका तकनीकी विवरण निम्न स्तर की कार्यान्वयन समस्या है जिसे भाषा स्वयं हल करना चाहती है। मैंने रिच हिकी को देखा कि वह एक वीडियो में क्लोजर के साथ यह कैसे करता है।
एंड्रयू मार्टिन

1
@ जेवरलेट: अधिक सटीक होना: एफपी में राज्य, यहां तक ​​कि उत्परिवर्तनीय स्थिति भी होती है, लेकिन वे उत्परिवर्तनीय चर का उपयोग करके इसका प्रतिनिधित्व नहीं करते हैं।
जियोर्जियो

9

जैसा कि @KarlBielefeldt ने नोट किया है, इस तरह की समस्या के लिए कार्यात्मक दृष्टिकोण इसे पिछले राज्य से एक नया राज्य लौटाने के रूप में देखना है। फ़ंक्शंस स्वयं कोई भी जानकारी नहीं रखते हैं, इसलिए वे हमेशा स्टेट मी से स्टेट एन में अपडेट करेंगे ।

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

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

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

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


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

@ डोभाल: "भले ही कंपाइलर ऐसा कर सकता है, यह केवल उन मामलों में संभव है जहां आप सूची के पिछले भाग पर पकड़ नहीं रखते हैं।": यह मुझे क्लीन में अनूठे प्रकारों की याद दिलाता है।
जियोर्जियो

4

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

रिच हिकी ने इन विचारों को प्रकाशित किया:

वहाँ अन्य वार्ता कर रहे हैं , लेकिन यह सही दिशा में भेजना चाहिए।


3

बड़े और मध्यम रूप से बड़े अनुप्रयोगों को लिखते समय, मैंने अक्सर यह पाया है कि एप्लिकेशन के उन अनुभागों के बीच अंतर करना उपयोगी होता है जो स्टेटफुल हैं और जो स्टेटलेस हैं।

राज्य अनुभाग में वर्ग / डेटा संरचनाएं एप्लिकेशन के डेटा को संग्रहीत करती हैं और इस अनुभाग में फ़ंक्शन एप्लिकेशन के डेटा के अंतर्निहित ज्ञान के साथ काम करती हैं।

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

सबसे कठिन हिस्सा यह पता लगा रहा है कि स्टेटलेस सेक्शन में कौन सी क्लास / फंक्शन लगाए जाएं और कौन सी क्लास / फंक्शन स्टेटफुल सेक्शन में रखे जाएं, और अलग फाइल / लाइब्रेरीज में रखने के लिए डिसिप्लिन हो।


यह प्रश्न का उत्तर कैसे देता है? (not-downvoting)
क्रैविमीर

@kravemir, चाहे आप ओओपी या एफपी का उपयोग करते हुए एक आवेदन लिखते हैं, आपको यह समझना होगा कि आवेदन की स्थिति कहां है।
आर साहू
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.