क्या कार्यात्मक विशेषताएं उन लाभों के लिए थोड़ा ओओपी भ्रम के लायक हैं जो वे लाते हैं?


13

हास्केल और एफ # में कार्यात्मक प्रोग्रामिंग सीखने के बाद, ओओपी प्रतिमान कक्षाओं, इंटरफेस, वस्तुओं के साथ पीछे-पीछे लगता है। एफपी के कौन से पहलुओं को मैं काम में ला सकता हूं जो मेरे सहकर्मी समझ सकते हैं? क्या कोई भी एफपी स्टाइल मेरे बॉस से मेरी टीम को वापस लेने के बारे में बात करने के लायक है ताकि हम उनका इस्तेमाल कर सकें?

FP के संभावित पहलू:

  • अचल स्थिति
  • आंशिक आवेदन और करी
  • प्रथम श्रेणी के कार्य (फ़ंक्शन पॉइंटर्स / फ़ंक्शनल ऑब्जेक्ट / रणनीति पैटर्न)
  • आलसी मूल्यांकन (और मोनड्स)
  • शुद्ध कार्य (कोई दुष्प्रभाव नहीं)
  • अभिव्यक्तियाँ (बनाम कथन - कोड की प्रत्येक पंक्ति साइड इफेक्ट्स पैदा करने के अलावा या इसके बजाय एक मान पैदा करती है)
  • प्रत्यावर्तन
  • पैटर्न मिलान

क्या यह एक फ्री-फॉर-ऑल है जहाँ हम प्रोग्रामिंग लैंग्वेज का समर्थन करने वाली भाषा के लिए जो कुछ भी करते हैं, वह कर सकते हैं? या एक बेहतर दिशानिर्देश है?


6
मुझे एक ऐसा ही अनुभव हुआ था। लगभग 2 महीने के दर्द के बाद मुझे "सामानों के लिए सामान" और "कार्यों के लिए नक्शे के सामान" सामान का एक अच्छा संतुलन खोजने लगा। यह किसी ऐसी गंभीर हैकिंग को करने में मदद करता है जो भाषा में दोनों का समर्थन करती है। इसके अंत में, मेरे FP और OOP दोनों कौशल में बहुत सुधार हुआ है
डैनियल ग्रैज़र

3
FWIW, Linq कार्यात्मक और आलसी दोनों है , और आप स्टेटिक तरीकों का उपयोग करके और राज्य की दृढ़ता से बचकर C # में कार्यात्मक प्रोग्रामिंग का अनुकरण कर सकते हैं।
रॉबर्ट हार्वे

1
इस बिंदु पर, आपको सिस्प को पढ़ना चाहिए । यह स्वतंत्र और अच्छी तरह से लिखा गया है। यह दो प्रतिमानों के बीच एक अच्छी तुलना प्रदान करता है।
साइमन बर्गोट

4
एफपी और ओओपी एक ही समय में कुछ अर्थ ऑर्थोगोनल और कुछ अर्थों में दोहरे हैं। OOP डेटा एब्स्ट्रैक्शन के बारे में है, एफपी के बारे में (अनुपस्थिति) साइड-इफेक्ट्स हैं। आपके साइड-इफेक्ट्स हैं या नहीं, आप अपने डेटा को कैसे अमूर्त करते हैं। उदाहरण के लिए लैम्ब्डा कैलकुलस कार्यात्मक और वस्तु-उन्मुख दोनों है। हां, एफपी आमतौर पर एब्सट्रैक्ट डेटा टाइप्स का इस्तेमाल करता है, न कि ऑब्जेक्ट्स का, लेकिन आप बिना एफपी कम होने के बजाय सिर्फ ऑब्जेक्ट्स का ही इस्तेमाल कर सकते हैं। OTOH, एक गहरा रिश्ता भी है: एक फ़ंक्शन केवल एक विधि के साथ एक वस्तु के लिए आइसोमोर्फिक है (यह है कि जावा में "फेक" कैसे किया जाता है, और जावा 8 में लागू किया जाता है, ...
Jörg W Mittag

3
मुझे लगता है कि आपके प्रश्न का सबसे मजबूत पहलू पठनीयता के साथ है। "ऑब्जेक्ट ओरिएंटेड दुकान पर काम करने के लिए कितना कार्यात्मक प्रोग्रामिंग शैली उपयुक्त है?" या क्या कार्यात्मक विशेषताएं उनके द्वारा लाए जाने वाले लाभों के लिए थोड़ा ओओपी भ्रम के लायक हैं।
ग्लेनपेटर्सन

जवाबों:


13

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

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

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

शुभ लाभ!


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

6

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

एक गणितज्ञ होने के नाते, मुझे फैंसी कार्यात्मक सामान बहुत आकर्षक लगते हैं, लेकिन यह आमतौर पर एक एप्लिकेशन डिज़ाइन करते समय उपयोगी होता है: ये संरचनाएं प्रोग्राम की संरचना में बहुत सारे आक्रमणकारियों को सांकेतिक शब्दों में बदल सकती हैं, बिना इन आक्रमणकारियों का प्रतिनिधित्व किए बिना।

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

रिकर्सन और पैटर्न मिलान का संयोजन उस विज़िटर डिज़ाइन पैटर्न की आवश्यकता को समाप्त करता है । बस आपको बूलियन अभिव्यक्तियों का मूल्यांकन करने वाले कोड की तुलना करने की आवश्यकता है: किसी भी कार्यात्मक प्रोग्रामिंग भाषा में यह कोड की लगभग 15 लाइनें होनी चाहिए, OOP में सही काम उस विज़िटर डिज़ाइन पैटर्न का उपयोग करना है , जो उस खिलौना-उदाहरण में बदल जाता है एक व्यापक निबंध। लाभ स्पष्ट हैं और मुझे किसी भी असुविधा के बारे में पता नहीं है।


2
मैं पूरी तरह से सहमत हूं, लेकिन मेरे पास उन लोगों से पुश-बैक है, जो पूरे उद्योग में सहमत हैं: वे आगंतुक पैटर्न को जानते हैं, उन्होंने इसे कई बार देखा है और इसका इस्तेमाल किया है इसलिए इसमें कोड कुछ ऐसा है जिसे वे समझते हैं और इससे परिचित हैं, अन्य दृष्टिकोण हालांकि हास्यास्पद सरल और आसान विदेशी है और इसलिए उनके लिए अधिक कठिन है। यह उद्योग का एक दुर्भाग्यपूर्ण तथ्य है कि 15+ साल का OOP हर प्रोग्रामर के सिर में धमाका करता है कि कोड की 100+ लाइनें उनके लिए 10 से अधिक समझना आसान है क्योंकि उन्होंने एक दशक में दोहराने के बाद 100+ लाइनों को याद किया है
जिमी हॉफा

1
-1 - अधिक terse कोड का मतलब यह नहीं है कि आप "कम" कोड लिख रहे हैं। आप कम वर्णों का उपयोग करके समान कोड लिख रहे हैं। यदि कुछ भी हो, तो आप अधिक त्रुटियां करते हैं क्योंकि कोड (अक्सर) पढ़ने में कठिन होता है।
तेलेस्टिन

8
@Telastyn: छंद अपठनीय के समान नहीं है। इसके अलावा, फूला हुआ बॉयलरप्लेट का विशाल द्रव्यमान अपठनीय होने का अपना तरीका है।
माइकल शॉ

1
@Telastyn मुझे लगता है कि आपने यहां असली क्रूक्स को छुआ है, हां टोन बुरा और अपठनीय हो सकता है, फूला हुआ भी बुरा और अपठनीय हो सकता है, लेकिन कुंजी चर लंबाई और puzzlically लिखित कोड नहीं है। कुंजी के रूप में आप आपरेशनों की संख्या से ऊपर उल्लेख किया है, मैं असहमत हूँ कि आपरेशनों की संख्या स्थिरता के लिए सहसंबंधित नहीं है, मुझे लगता है कि कम चीजें (स्पष्ट रूप से लिखित कोड के साथ) करने से पठनीयता और स्थिरता का लाभ होता है । स्पष्ट रूप से एकल अक्षर फ़ंक्शन और चर नामों के साथ समान संख्या में काम करने में मदद नहीं मिलेगी, अच्छा एफपी को काफी कम संचालन की आवश्यकता है जो अभी भी स्पष्ट रूप से लिखा गया है
जिमी होफा

2
@ user949300: यदि आप एक पूरी तरह से अलग उदाहरण चाहते हैं, यह कैसे जावा 8 उदाहरण ?: के बारे में list.forEach(System.out::println);देखने का एक एफपी बिंदु से, printlnएक समारोह दो तर्क, एक लक्ष्य ले रहा है PrintStreamऔर एक मूल्य Objectहै, लेकिन Collectionकी forEachविधि एक तर्क की आशा के साथ एक समारोह केवल जिसे हर तत्व पर लागू किया जा सकता है। तो पहला तर्क System.outएक नए फ़ंक्शन के लिए एक तर्क के साथ उपज में पाए जाने वाले उदाहरण के लिए बाध्य है । यह आसान हैBiConsumer<…> c=PrintStream::println; PrintStream a1=System.out; list.forEach(a2 -> c.accept(a1, a2));
Holger

5

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

एफपी और ओओपी परस्पर अनन्य नहीं हैं। स्काला को देखो। कुछ लोग सोचते हैं कि यह सबसे खराब है क्योंकि यह अशुद्ध एफपी है, लेकिन कुछ लोग सोचते हैं कि यह उसी कारण के लिए सबसे अच्छा है।

एक के बाद एक, यहाँ कुछ पहलू हैं जो OOP के साथ काम करते हैं:

  • शुद्ध कार्य (कोई साइड इफेक्ट नहीं) - मुझे पता है कि हर प्रोग्रामिंग भाषा इस का समर्थन करती है। वे आपके कोड को बहुत आसान बनाते हैं, इसके बारे में तर्क करना बहुत आसान है और जब भी व्यावहारिक होना चाहिए। आपको इसे FP कहने की जरूरत नहीं है। बस इसे अच्छी कोडिंग प्रैक्टिस कहें।

  • अपरिवर्तनीयता: स्ट्रिंग यकीनन सबसे अधिक इस्तेमाल की जाने वाली जावा ऑब्जेक्ट है और यह अपरिवर्तनीय है। मैं अपने ब्लॉग पर अपरिवर्तनीय जावा ऑब्जेक्ट्स और अपरिवर्तनीय जावा कलेक्शंस को कवर करता हूं। आप में से कुछ आपके लिए लागू हो सकते हैं।

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

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

  • अभिव्यक्तियाँ (बनाम कथन - कोड की प्रत्येक पंक्ति साइड इफेक्ट्स पैदा करने के अलावा, या इसके बजाय एक मान पैदा करती है) - C, C ++ और जावा में एकमात्र मूल्यांकनकर्ता ऑपरेटर टर्नेरी ऑपरेटर है । मैं अपने ब्लॉग पर उचित उपयोग पर चर्चा करता हूं। आप पा सकते हैं कि आप कुछ सरल कार्य लिख सकते हैं जो पुन: प्रयोज्य और मूल्यांकन योग्य हैं।

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

  • आंशिक आवेदन और करी - प्रथम श्रेणी के कार्यों के बिना व्यावहारिक नहीं।

  • पैटर्न मिलान - आमतौर पर ओओपी में हतोत्साहित किया जाता है।

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


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

C # में वास्तव में मुझे परेशान करता है कि मैं 2 सरल कारणों से एक-विधि इंटरफेस के बजाय प्रतिनिधियों का उपयोग नहीं कर सकता: 1. आप एक हैक के बिना पुनरावर्ती लैंब नहीं बना सकते हैं (पहले अशक्त करने के लिए और फिर एक लंबोदर सेकंड या Y- के लिए कॉम्बिनेटर (जो सी # में नरक के रूप में बदसूरत है)। 2. कोई प्रकार के उपनाम नहीं हैं जो आप परियोजना के दायरे में उपयोग कर सकते हैं, इसलिए आपके प्रतिनिधियों के हस्ताक्षर बहुत जल्दी असहनीय हो जाते हैं। तो सिर्फ इन 2 बेवकूफ कारणों के लिए मैं C # का आनंद नहीं ले सकता, क्योंकि केवल एक चीज जो मैं इसे काम कर सकता हूं वह है एक-विधि इंटरफेस का उपयोग करके जो सिर्फ अनावश्यक अतिरिक्त काम है।
ट्रिडेंट

@bonomo Java 8 में एक सामान्य java.util.function.BiConsumer है जो C # में उपयोगी हो सकता है: public interface BiConsumer<T, U> { public void accept(T t, U u); }java.util.function में अन्य उपयोगी कार्यात्मक इंटरफेस हैं।
ग्लेनपेटर्सन

@bonomo अरे मैं समझ गया, यह हास्केल का दर्द है। जब भी आप किसी को पढ़ते हैं तो कहते हैं "लर्निंग एफपी ने मुझे ओओपी में बेहतर बना दिया" का अर्थ है कि उन्होंने रूबी या ऐसा कुछ सीखा जो यास्केल की तरह शुद्ध और घोषणात्मक नहीं है। हास्केल यह स्पष्ट करता है कि ओओपी बेकार निम्न स्तर है। आपके द्वारा चलाए जा रहे सबसे बड़े दर्द यह है कि जब आप एचएम प्रकार की प्रणाली में नहीं होते हैं, तो बाधा-आधारित प्रकार का अनुमान अजेय है, इसलिए कॉशनट्रंट-आधारित प्रकार का निष्कर्ष पूरी तरह से नहीं किया जाता है: blogs.msdn.com/b/ericlippert-archive / २०१२ / ०३ / ० ९ /…
जिम्मी होफा

1
Most OOP languages don't have the stack space for it वास्तव में? संतुलित बाइनरी ट्री में अरबों नोड्स को प्रबंधित करने के लिए आपको केवल 30 स्तरों की पुनरावृत्ति की आवश्यकता होगी। मुझे पूरा यकीन है कि मेरा स्टैक स्पेस इससे कई अधिक स्तरों के लिए उपयुक्त है।
रॉबर्ट हार्वे

3

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

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


2

एक प्रोग्रामर के रूप में मुझे लगता है कि आपको सीखना बंद नहीं करना चाहिए। उस ने कहा, यह बहुत दिलचस्प है कि एफपी सीखना आपके ओओपी कौशल को कम कर रहा है। मैं ओओपी सीखने के बारे में सोचता हूं कि बाइक चलाना कैसे सीखें; आप कभी नहीं भूलेंगे कि यह कैसे करना है।

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

जैसा कि आप अधिक अनुभव प्राप्त करते हैं, कोर प्रोग्रामिंग अवधारणाओं को खोना बहुत कठिन होगा। इसलिए मेरा सुझाव है कि जब तक आपके दिमाग में ओओपी अवधारणा पूरी तरह से जम न जाए, तब तक आप एफपी पर इसे आसान बना सकते हैं। एफपी एक निश्चित प्रतिमान बदलाव है। सौभाग्य!


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

@ SK-लॉजिक, मुझे आपका मेथफोर पसंद है
Trident D'Gao

@ एसके-लॉजिक: सीखने की अनिवार्य प्रोग्रामिंग क्या है? अपने आप को अपने पेट पर खींचकर?
रॉबर्ट हार्वे

@ रोबर्टहवे एक जंग खाए चम्मच और पंचकार्ड के एक डेक के साथ भूमिगत को दफनाने की कोशिश कर रहा है।
जिमी हॉफ

0

कई अच्छे जवाब पहले से ही हैं, इसलिए मेरा आपके सवाल का एक सबसेट को संबोधित करेगा; अर्थात्, मैं आपके प्रश्न के आधार पर umbrage लेता हूं, क्योंकि OOP और कार्यात्मक विशेषताएं परस्पर अनन्य नहीं हैं।

यदि आप C ++ 11 का उपयोग करते हैं, तो भाषा / मानक पुस्तकालय में निर्मित कार्यात्मक-प्रोग्रामिंग सुविधाओं के इन प्रकार के बहुत सारे हैं जो OOP के साथ अच्छी तरह से तालमेल (सुंदर) करते हैं। बेशक, मुझे यकीन नहीं है कि टीएमपी आपके बॉस या सहकर्मियों द्वारा कितनी अच्छी तरह से प्राप्त किया जाएगा, लेकिन मुद्दा यह है कि आप इनमें से कई सुविधाओं को किसी न किसी रूप में गैर-कार्यात्मक / ओओपी भाषाओं में प्राप्त कर सकते हैं, जैसे कि सी ++।

संकलित समय पुनरावृत्ति के साथ टेम्पलेट्स का उपयोग करना आपके पहले 3 बिंदुओं पर निर्भर करता है,

  • अचल स्थिति
  • प्रत्यावर्तन
  • पैटर्न मिलान

उस टेम्पलेट-मान में अपरिवर्तनीय (संकलन-समय स्थिरांक) हैं, किसी भी पुनरावृत्ति का उपयोग पुनरावृत्ति का उपयोग करके किया जाता है, और ब्रोचिंग को अधिभार संकल्प के रूप में (अधिक या कम) पैटर्न मिलान का उपयोग करके किया जाता है।

अन्य बिंदुओं के लिए, का उपयोग करके std::bindऔर std::functionआपको आंशिक फ़ंक्शन अनुप्रयोग देता है, और फ़ंक्शन पॉइंटर्स भाषा में अंतर्निहित होते हैं। कॉल करने योग्य ऑब्जेक्ट कार्यात्मक ऑब्जेक्ट (साथ ही आंशिक फ़ंक्शन अनुप्रयोग) हैं। ध्यान दें कि कॉल करने योग्य वस्तुओं से मेरा मतलब है कि उनकी परिभाषा operator ()

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

अंत में, यहाँ आंशिक फ़ंक्शन अनुप्रयोग के साथ संकलन-समय पुनरावृत्ति का उपयोग करने का एक उदाहरण है। यह कुछ हद तक विरोधाभासी उदाहरण है, लेकिन यह ऊपर के अधिकांश बिंदुओं को प्रदर्शित करता है। यह एक दिए गए फ़ंक्शन के लिए एक दिए गए टपल में मानों को पुन: बाँध देगा और एक (कॉल करने योग्य) फ़ंक्शन ऑब्जेक्ट उत्पन्न करेगा

#include <iostream>
#include <functional>

//holds a compile-time index sequence
template<std::size_t ... >
struct index_seq
{};

//builds the index_seq<...> struct with the indices (boils down to compile-time indexing)
template<std::size_t N, std::size_t ... Seq>
struct gen_indices
  : gen_indices<N-1, N-1, Seq ... >
{};

template<std::size_t ... Seq>
struct gen_indices<0, Seq ... >
{
    typedef index_seq<Seq ... > type;
};


template <typename RType>
struct bind_to_fcn
{
    template <class Fcn, class ... Args>
    std::function<RType()> fcn_bind(Fcn fcn, std::tuple<Args...> params)
    {
        return bindFunc(typename gen_indices<sizeof...(Args)>::type(), fcn, params);
    }

    template<std::size_t ... Seq, class Fcn, class ... Args>
    std::function<RType()> bindFunc(index_seq<Seq...>, Fcn fcn, std::tuple<Args...> params)
    {
        return std::bind(fcn, std::get<Seq>(params) ...);
    }
};

//some arbitrary testing function to use
double foo(int x, float y, double z)
{
    return x + y + z;
}

int main(void)
{
    //some tuple of parameters to use in the function call
    std::tuple<int, float, double> t = std::make_tuple(1, 2.04, 0.1);                                                                                                                                                                                                      
    typedef double(*SumFcn)(int,float,double);

    bind_to_fcn<double> binder;
    auto other_fcn_obj = binder.fcn_bind<SumFcn>(foo, t);
    std::cout << other_fcn_obj() << std::endl;
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.