असाइनमेंट ऑपरेटर या लूप्स का उपयोग कार्यात्मक प्रोग्रामिंग में हतोत्साहित क्यों?


9

यदि मेरा फ़ंक्शन दो आवश्यकताओं से नीचे मिलता है, तो मेरा मानना ​​है कि Sum किसी सूची में आइटम के सारांश को वापस करने के लिए फ़ंक्शन जहां आइटम दी गई स्थिति के लिए सही का मूल्यांकन करता है, उसे शुद्ध फ़ंक्शन के रूप में निर्दिष्ट किया जाना चाहिए?

1) i / p के दिए गए सेट के लिए, एक ही ओ / पी समय की परवाह किए बिना वापस लौटा दिया जाता है जब फ़ंक्शन कहा जाता है

2) इसका कोई साइड इफेक्ट नहीं है

public int Sum(Func<int,bool> predicate, IEnumerable<int> numbers){
    int result = 0;
    foreach(var item in numbers)
        if(predicate(item)) result += item;
    return result;
}

उदाहरण : Sum(x=>x%2==0, new List<int> {1,2,3,4,5...100});

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


1
इसका कोई साइड इफेक्ट नहीं है - इसका साइड इफेक्ट है, जब itemलूप में परिवर्तनशील परिवर्तन होता है।
फैबियो

@ फैबियो ठीक है। लेकिन क्या आप साइड इफेक्ट के दायरे में विस्तार कर सकते हैं?
rahulaga_dev

जवाबों:


16

कार्यात्मक प्रोग्रामिंग में ऐसा क्या है जिससे फर्क पड़ता है?

फंक्शनल प्रोग्रामिंग सिद्धांत घोषणात्मक द्वारा होता है । आप कहते हैं कि इसके बजाय आपका परिणाम क्या है, इसकी गणना कैसे करें।

आइए आपके स्निपेट के वास्तव में कार्यात्मक कार्यान्वयन पर एक नज़र डालें। हास्केल में यह होगा:

predsum pred numbers = sum (filter pred numbers)

क्या यह स्पष्ट है कि परिणाम क्या है? काफी, यह संख्या को विधेय से मिलने का योग है। इसकी गणना कैसे की जाती है? मुझे परवाह नहीं है, संकलक से पूछें।

आप संभवतः कह सकते हैं कि का उपयोग करते हुए sumऔर filterएक चाल है और यह गणना नहीं करता। फिर इन सहायकों के बिना इसे लागू करने दें (हालांकि सबसे अच्छा तरीका उन्हें पहले लागू करना होगा)।

"कार्यात्मक प्रोग्रामिंग 101" समाधान जो उपयोग नहीं करता sumहै वह पुनरावृत्ति के साथ है:

sum pred list = 
    case list of
        [] -> 0
        h:t -> if pred h then h + sum pred t
                         else sum pred t

यह अभी भी बहुत स्पष्ट है कि एकल फ़ंक्शन कॉल के संदर्भ में क्या परिणाम है। यह या तो 0, या recursive call + h or 0, पर निर्भर करता है pred h। अभी भी बहुत कठिन है, भले ही अंतिम परिणाम तुरंत स्पष्ट नहीं है (हालांकि थोड़ा अभ्यास के साथ यह वास्तव में forलूप की तरह ही पढ़ता है )।

अपने संस्करण की तुलना करें:

public int Sum(Func<int,bool> predicate, IEnumerable<int> numbers){
    int result = 0;
    foreach(var item in numbers)
        if (predicate(item)) result += item;
    return result;
}

इसका परिणाम क्या है? ओह, मैं देख रहा हूं: एकल returnकथन, यहां कोई आश्चर्य नहीं return result:।

लेकिन क्या है result? int result = 0? सही नहीं लगता। आप उसके साथ बाद में कुछ करें 0। ठीक है, आप itemइसे जोड़ते हैं । और इसी तरह।

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

तो, चर और छोरों गलत हैं?

नहीं।

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

चर और छोरों बस कार्यात्मक प्रोग्रामिंग नहीं हैं।

सारांश

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

अधिकांश व्यापक भाषाएं आपको कुछ कार्यात्मक निर्माणों का उपयोग करने की अनुमति देती हैं। पायथन में उदाहरण के लिए आप इनमें से चुन सकते हैं:

result = 0
for num in numbers:
    if pred(result):
        result += num
return result

या

return sum(filter(pred, numbers))

या

return sum(n for n in numbers if pred(n))

ये कार्यात्मक अभिव्यक्तियाँ उस तरह की समस्याओं के लिए अच्छी तरह से फिट होती हैं और बस कोड को छोटा (और छोटा अच्छा है ) बनाती है। आपको विचारशील रूप से उनके साथ अनिवार्य कोड को प्रतिस्थापित नहीं करना चाहिए, लेकिन जब वे फिट होते हैं, तो वे लगभग हमेशा एक बेहतर विकल्प होते हैं।


अच्छी व्याख्या के लिए thx !!
rahulaga_dev

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

1
@Frax: धन्यवाद !! मैं इस पर ध्यान दूँगा। इसके अलावा हाल ही में रिच हिकी में मूल्यों के मूल्य पर बात की गई है यह वास्तव में शानदार है। मुझे लगता है कि एक अंगूठे का नियम - "मान और अभिव्यक्ति के साथ काम करने के बजाय कुछ धारण मूल्य के साथ काम कर सकते हैं और बदल सकते हैं"
rahulaga_dev

1
@ फ़्रेक्स: यह भी कहना उचित है कि एफपी अनिवार्य प्रोग्रामिंग पर एक अमूर्त है - क्योंकि अंततः किसी को "कैसे करना है" पर मशीन को निर्देश देना है, है ना? यदि हाँ, तो क्या एफपी की तुलना में अनिवार्य प्रोग्रामिंग का निम्न स्तर का नियंत्रण नहीं है?
राहुलगा_देव

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

9

परिवर्तनशील राज्य का उपयोग आम तौर पर कार्यात्मक प्रोग्रामिंग में हतोत्साहित किया जाता है। परिणाम के रूप में लूप को हतोत्साहित किया जाता है, क्योंकि लूप केवल उत्परिवर्तनीय स्थिति के साथ संयोजन में उपयोगी होते हैं।

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

आपके मामले में, आप लिख सकते हैं numbers.Where(predicate).Sum()जो स्पष्ट रूप से बहुत सरल है। और सरल का मतलब है कम बग।


धन्यवाद !! मुझे लगता है कि मैं हड़ताली लाइन याद कर रहा था - लेकिन कार्यात्मक प्रोग्रामिंग का प्रतिमान न केवल पूरे कार्यों के स्तर पर लागू होता है, लेकिन अब मैं यह भी सोच रहा हूं कि इस सीमा की कल्पना कैसे करें। मूल रूप से उपभोक्ता के नजरिए से यह शुद्ध कार्य है लेकिन डेवलपर जिसने वास्तव में इस फ़ंक्शन को लिखा है, ने शुद्ध फ़ंक्शन दिशानिर्देशों का पालन नहीं किया है? उलझन :(
rahulaga_dev

@ राहुल अग्रवाल: क्या सीमा?
जैक्सबी

मैं इस अर्थ में भ्रमित हूं कि क्या प्रोग्रामिंग प्रतिमान कार्य के परिप्रेक्ष्य से उपभोक्ता के रूप में एफपी होने के योग्य है? Bcoz अगर मैं के कार्यान्वयन कार्यान्वयन पर देखने Whereमें numbers.Where(predicate).Sum()- यह का उपयोग करता है foreachपाश।
rahulaga_dev

3
@RahulAgarwal: किसी फ़ंक्शन के उपभोक्ता के रूप में, यदि कोई फ़ंक्शन या मॉड्यूल आंतरिक रूप से परस्पर स्थिति का उपयोग करता है, तो यह बाहरी रूप से शुद्ध होने पर वास्तव में परवाह नहीं करता है।
जैक्सबी

7

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

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

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