कार्यात्मक कार्यक्रमों का संकलन सफलता और शुद्धता के बीच संबंध क्यों है?


12

मैं 4 साल से कार्यात्मक प्रोग्रामिंग की ओर रुझान कर रहा हूं, जब से मैंने पहली बार LINQ के साथ काम करना शुरू किया है। हाल ही में, मैंने कुछ शुद्ध कार्यात्मक C # कोड लिखे और मैंने देखा, पहला हाथ, जो मैंने कार्यात्मक कार्यक्रमों के बारे में पढ़ा है - जो कि एक बार संकलन करने के बाद वे सही हो जाते हैं।

मैंने एक उंगली डालने की कोशिश की कि यह मामला क्यों है लेकिन मैं सफल नहीं हुआ हूं।

एक अनुमान यह है कि OO रियासतों को लागू करने में, आपके पास "अमूर्त परत" है जो कार्यात्मक कार्यक्रमों में मौजूद नहीं है और यह अमूर्त परत वस्तुओं के बीच के अनुबंधों के लिए संभव है, जबकि कार्यान्वयन गलत है।

क्या किसी ने इसके बारे में सोचा है और कार्यात्मक प्रोग्रामिंग में संकलन की सफलता और कार्यक्रम की शुद्धता के बीच संबंध के अंतर्निहित अमूर्त कारण के साथ आया है?


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

1
@delnan मैं यह नहीं कहूंगा कि लिस्प एक कार्यात्मक प्रोग्रामिंग भाषा है, हालांकि इसका उपयोग कार्यात्मक प्रोग्रामिंग कोड लिखने के लिए किया जा सकता है। क्लजुरे जो एक लिस्प बोली है, एक कार्यात्मक प्रोग्रामिंग भाषा है
साकिस

2
मैं @delnan से सहमत हूँ। यह कथन सांख्यिकीय रूप से टाइप की गई कार्यात्मक प्रोग्रामिंग भाषाओं से संबंधित है, विशेष रूप से हास्केल जो हिंदले-मिलनर प्रणाली का उपयोग करता है। मुझे लगता है कि मुख्य विचार यह है कि यदि आप प्रकार सही विश्वास प्राप्त करते हैं कि आपका कार्यक्रम सही है तो वृद्धि हुई है।
साकिस

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

1
नहीं एक पूरा जवाब है, लेकिन कार्यक्रम के टाइपिंग है कार्यक्रम के औपचारिक सत्यापन का अपरिष्कृत रूप। सामान्य ऑब्जेक्ट ओरिएंटेड प्रोग्रामों में या तो जटिल या बहुत सरल प्रकार के सिस्टम होते हैं, क्योंकि प्रतिस्थापन को ध्यान में रखने की आवश्यकता होती है - ज्यादातर मामलों में उन्हें सुविधा के लिए निराधार बना दिया जाता है। MLOH जैसी विधियाँ पूरी तरह से CH का उपयोग कर सकती हैं ताकि आप किसी प्रूफ को केवल प्रकारों में एन्कोड कर सकें और कंपाइलर को प्रूफ चेकर के रूप में उपयोग कर सकें।
मैकीज पीचोटका

जवाबों:


12

मैं इस उत्तर को किसी ऐसे व्यक्ति के रूप में लिख सकता हूं, जो चीजों को बहुत कुछ साबित करता है, इसलिए मेरे लिए शुद्धता सिर्फ वह नहीं है जो काम करता है, लेकिन क्या काम करता है और यह साबित करना आसान है।

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

हालांकि, जब से हमने अग्रिम में पिपर का भुगतान किया है, हमारे पास निपटने के लिए बहुत कम है और हमारे पास बहुत कम विकल्प हैं कि चीजें कैसे गलत हो सकती हैं। यदि आपका 1984 का प्रशंसक, स्वतंत्रता वास्तव में गुलामी है! एक कार्यक्रम के लिए 101 विभिन्न स्वच्छ चाल का उपयोग करके, हमें चीजों के बारे में तर्क करना होगा जैसे कि इन 101 चीजों में से कोई भी हो सकता है! जैसा कि यह पता चला है कि वास्तव में करना मुश्किल है :)

यदि आप तलवार के बजाय सुरक्षा कैंची से शुरू करते हैं, तो चलना मामूली कम खतरनाक है।

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

जैसा कि आप सुविधाओं और उनके बीच जटिल इंटरैक्शन को जोड़ते हैं, जो कि टाइप सिस्टम के बढ़ने से नहीं जांचा जाता है। हालाँकि, अनौपचारिक साक्ष्यों के निर्माण की आपकी क्षमता में सुधार नहीं हुआ है! इसका मतलब यह है कि आपके प्रारंभिक निरीक्षण के माध्यम से फिसल सकता है और बाद में पकड़ा जाना चाहिए।


1
मुझे आपका उत्तर पसंद है लेकिन मैं यह नहीं देखता कि यह ओपी के प्रश्न का उत्तर कैसे देता है
sakisk

1
@ अल्फा ने मेरे उत्तर का विस्तार किया। TLDR: हर कोई एक गणितज्ञ है।
डैनियल ग्रैज़र

"एक कार्यक्रम के लिए 101 विभिन्न स्वच्छ तरकीबों का उपयोग करके, हमें चीजों के बारे में तर्क करना होगा क्योंकि इनमें से कोई भी 101 चीजें हो सकती हैं!": मैंने कहीं पढ़ा है कि आपको उत्परिवर्तन के साथ कार्यक्रम करने के लिए एक प्रतिभाशाली होने की आवश्यकता है, क्योंकि आपको इसे रखना होगा आपके सिर में बहुत जानकारी।
जियोर्जियो

12

कार्यात्मक प्रोग्रामिंग में संकलन सफलता और कार्यक्रम शुद्धता के बीच संबंध के लिए अंतर्निहित अमूर्त कारण?

परस्पर अवस्था।

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

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

यदि आप कार्यात्मक प्रोग्रामिंग अच्छी तरह से कर रहे हैं, तो कोई (या बहुत कम) परस्पर अवस्था नहीं है।

हालांकि यहाँ कार्य-कारण के बारे में कुछ बहस है - यदि राज्य के बिना कार्यक्रम अधिक बार संकलन के बाद काम करते हैं क्योंकि संकलनकर्ता अधिक बग पकड़ सकता है या यदि राज्य के बिना कार्यक्रम अधिक बार संकलन के बाद काम करते हैं, क्योंकि प्रोग्रामिंग की शैली कम बग पैदा करती है।

यह मेरे अनुभव में दोनों का मिश्रण है।


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

7

बस इसे लगाने के लिए, प्रतिबंध का मतलब है कि चीजों को एक साथ रखने के लिए कम सही तरीके हैं, और प्रथम श्रेणी के कार्यों से लूप संरचनाओं के लिए चीजों को बाहर निकालना आसान हो जाता है। उदाहरण के लिए, इस उत्तर से लूप लें :

for (Iterator<String> iterator = list.iterator(); iterator.hasNext();) {
    String string = iterator.next();
    if (string.isEmpty()) {
        iterator.remove();
    }
}

जब आप इसके माध्यम से पुनरावृत्ति कर रहे हों, तो किसी तत्व को संग्रह से निकालने के लिए जावा में यह एक सुरक्षित अनिवार्य तरीका होता है। बहुत सारे तरीके हैं जो बहुत करीब लगते हैं, लेकिन गलत हैं। इस पद्धति से अनजान लोग कभी-कभी समस्या से बचने के लिए जटिल तरीकों से गुजरते हैं, जैसे कि एक प्रति के माध्यम से पुनरावृत्ति करना।

यह सामान्य बनाना बहुत मुश्किल नहीं है, इसलिए यह सिर्फ संग्रह से अधिक पर काम करेगा Strings, लेकिन प्रथम श्रेणी के कार्यों के बिना, आप विधेय (स्थिति के अंदर if) को प्रतिस्थापित नहीं कर सकते हैं , इसलिए यह कोड कॉपी और चिपकाया जाता है और थोड़ा संशोधित किया गया।

प्रथम श्रेणी के कार्यों को मिलाएं जो आपको एक पैरामीटर के रूप में विधेय को पारित करने की क्षमता प्रदान करते हैं, अपरिवर्तनीयता के प्रतिबंध के साथ जो आपको बहुत परेशान करता है अगर आप नहीं करते हैं, और आप filterइस बिल्डिंग कोड में जैसे साधारण बिल्डिंग ब्लॉकों के साथ आते हैं। वही काम करता है:

list filter (!_.isEmpty)

अब इस बारे में सोचें कि स्काला के मामले में संकलित समय पर आपके लिए किस प्रकार की प्रणाली की जाँच की जाती है, लेकिन ये जाँचें डायनामिक प्रकार की प्रणालियों द्वारा भी की जाती हैं जब आप इसे चलाते हैं:

  • listकिसी प्रकार का होना चाहिए जो filterविधि का समर्थन करता है , अर्थात् एक संग्रह।
  • तत्वों में listएक isEmptyविधि होनी चाहिए जो एक बूलियन लौटाती है।
  • आउटपुट एक ही प्रकार के तत्वों के साथ एक (संभावित) छोटा संग्रह होगा।

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

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

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


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

2

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

प्रोग्रामिंग भाषा का पहलू जो किसी भी तरह रनटाइम प्रकार की शुद्धता के साथ सफल संकलन को सहसंबंधित कर सकता है, जैसा कि आप वर्णन करते हैं, स्थैतिक टाइपिंग है, और तब भी, यदि आप केवल जातियों के साथ टाइप चेकर को कमजोर नहीं कर रहे हैं जो केवल रनटाइम पर मुखर हो सकते हैं (वातावरण में साथ दृढ़ता से टाइप किए गए मान या स्थान, जैसे जावा या .net) या बिल्कुल नहीं (ऐसे वातावरण में जहां प्रकार की जानकारी खो जाती है या कमजोर टाइपिंग के साथ, जैसे C और C ++)।

हालांकि, प्रति से कार्यात्मक प्रोग्रामिंग अन्य तरीकों से मदद कर सकता है, जैसे कि साझा डेटा और उत्परिवर्तनीय स्थिति से बचना।

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


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

2

प्रबंधकों के लिए स्पष्टीकरण:

एक कार्यात्मक कार्यक्रम एक बड़ी मशीन की तरह है जहां सब कुछ जुड़ा हुआ है, ट्यूब, केबल। [एक गाडी]

एक प्रक्रियात्मक कार्यक्रम एक ऐसी मशीन की तरह होता है जिसमें एक छोटी मशीन होती है, जिसमें आंशिक उत्पादों को डिब्बे में रखकर, कहीं और से आंशिक उत्पाद प्राप्त होते हैं। [एक कारखाना]

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


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

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


1
बेहतर धर्मशास्त्र: कार्यात्मक प्रोग्रामिंग ग्राहकों के बिना एक मदद डेस्क की तरह है - सब कुछ अद्भुत है (जब तक आप उद्देश्य या दक्षता पर सवाल नहीं उठाते हैं)।
ब्रेंडन

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

बड़े पैमाने पर कार्यात्मक प्रोग्रामिंग एक en.wikipedia.org/wiki/Spherical_cow के लिए बहुत अच्छी तरह से काम करता है इसे स्थानीय रखें।
डेन

@ क्या मैं खुद भी बड़े स्तर की एफपी परियोजना पर काम करने में कोई व्यवहार्यता की समस्या से डरूँगा। यहां तक ​​कि इसे प्यार करते हैं। सामान्यीकरण की अपनी सीमा है। लेकिन जैसा कि अंतिम वक्तव्य एक सामान्यीकरण भी है ... (गोलाकार गाय के लिए धन्यवाद)
जोप एगेन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.