कार्यात्मक प्रोग्रामिंग प्रस्तावक इस कथन को कोड कंप्लीट में कैसे उत्तर देंगे?


30

दूसरे संस्करण के पृष्ठ 839 पर, स्टीव मैककोनेल उन सभी तरीकों पर चर्चा कर रहे हैं जो प्रोग्रामर बड़े कार्यक्रमों में "जटिलता को जीत सकते हैं"। उनके सुझाव इस कथन के साथ समाप्त होते हैं:

"ऑब्जेक्ट ओरिएंटेड प्रोग्रामिंग पर लागू होने वाला अमूर्त के एक स्तर प्रदान करता है एक ही समय में एल्गोरिदम और डेटा अमूर्त कि कार्यात्मक अपघटन अकेले नहीं प्रदान की थी का एक प्रकार,।"

अपने निष्कर्ष के साथ कि "जटिलता को कम करना एक प्रभावी प्रोग्रामर होने के लिए सबसे महत्वपूर्ण कुंजी है" (एक ही पृष्ठ), यह कार्यात्मक प्रोग्रामिंग के लिए बहुत अधिक चुनौती है।

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

अगर हमने एफपी और ओओ के बीच तुलना की शर्तों को समसामयिक मुद्दों या वैश्विक जटिलता के प्रबंधन के लिए पुन: प्रयोज्यता जैसे मुद्दों से स्थानांतरित कर दिया, तो यह बहस कैसे दिखेगी?

संपादित करें

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

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


3
+1 के बावजूद सवाल को विरोधी के बजाय फंसाया गया है, यह एक अच्छा सवाल है।
मटनज़

16
जैसा कि कई जवाबों में कहा गया है, कार्यात्मक अपघटन और कार्यात्मक प्रोग्रामिंग दो अलग-अलग जानवर हैं। इसलिए निष्कर्ष है कि "यह कार्यात्मक प्रोग्रामिंग के लिए बहुत अधिक चुनौती है" स्पष्ट रूप से गलत है, इसका इससे कोई लेना-देना नहीं है।
Fabio Fracassi

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

6
@ एसके-लॉजिक ऑल मैककोनेल ने कहा कि "कार्यात्मक अपघटन अकेले" ओओपी के रूप में अमूर्तता के समान साधन प्रदान नहीं करता है, जो मुझे एक बहुत ही सुरक्षित कथन लगता है। कहीं भी वह यह नहीं कहता है कि FP भाषाओं में सार के रूप में OOP जितना शक्तिशाली नहीं है। वास्तव में वह एफपी भाषाओं का उल्लेख नहीं करता है। यह सिर्फ ओपी की व्याख्या है।
sepp2k

2
@ sepp2k, ठीक है, मैं देखता हूं। लेकिन फिर भी, डेटा संरचनाओं का एक बहुत ही जटिल और अच्छी तरह से स्तरित प्रणाली और प्रसंस्करण अमूर्त लगभग शुद्ध लैम्ब्डा पथरी के लिए कुछ भी नहीं बल्कि कार्यात्मक अपघटन के शीर्ष पर बनाया जा सकता है - मॉड्यूल व्यवहार का अनुकरण करके। OO अमूर्त की कोई आवश्यकता नहीं है।
एसके-तर्क

जवाबों:


13

ध्यान रखें कि पुस्तक 20 साल से अधिक समय तक लिखी गई थी। दिन के पेशेवर प्रोग्रामर के लिए, FP मौजूद नहीं था - यह पूरी तरह से शिक्षाविदों और शोधकर्ताओं के दायरे में था।

हमें कार्य के उचित संदर्भ में "कार्यात्मक अपघटन" को फ्रेम करने की आवश्यकता है। लेखक कार्यात्मक प्रोग्रामिंग का जिक्र नहीं कर रहा है। हमें इसे "संरचित प्रोग्रामिंग" और GOTOउससे पहले भरे गए गड़बड़ से जोड़ने की आवश्यकता है। यदि आपके संदर्भ में एक पुराना FORTRAN / COBOL / BASIC है, जिसमें फ़ंक्शंस नहीं थे (हो सकता है, अगर आप भाग्यशाली थे तो आपको GOSUB का एक भी स्तर मिलेगा) और आपके सभी चर वैश्विक हैं, जो आपके प्रोग्राम को तोड़ने में सक्षम हैं कार्यों की परतों में एक प्रमुख वरदान है।

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


27

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

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


10
+1 "कार्यात्मक अपघटन"! = "कार्यात्मक प्रोग्रामिंग"। पहला क्लासिक अनुक्रमिक कोडिंग पर निर्भर करता है, जिसमें वेनिला डेटा स्ट्रक्चर्स का उपयोग किया गया है, जिसमें (या केवल हाथ से रोल) इनहेरिटेंस, एनकैप्सुलेशन और पॉलीमोर्फिज़्म है। दूसरा लैम्ब्डा कैलकुलस का उपयोग करके समाधान व्यक्त करता है। दो पूरी तरह से अलग चीजें।
बाइनरी वॉरियर

4
माफी, लेकिन वाक्यांश "प्रक्रियात्मक प्रोग्रामिंग" हठपूर्वक दिमाग में आने से पहले मना कर दिया। मेरे लिए "कार्यात्मक अपघटन" कार्यात्मक प्रोग्रामिंग की तुलना में प्रक्रियात्मक प्रोग्रामिंग का कहीं अधिक संकेत है।
बाइनरी वॉरियर

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

स्टुअर्ट हल्लोवे उद्धरण के लिए लिंक: Thinkrelevance.com/blog/2009/08/12/…
dan

2
@dan यह हो सकता है कि यह गतिशील रूप से टाइप की गई भाषा क्लोजर में कैसे किया जाता है (मुझे नहीं पता, मैं क्लूज्योर का उपयोग नहीं करता हूं), लेकिन मुझे लगता है कि इससे निष्कर्ष निकालना खतरनाक है, कि यह एफपी सामान्य रूप से कैसे किया जाता है। हास्केल लोग, उदाहरण के लिए, सार प्रकार और जानकारी छिपाने पर बहुत बड़े प्रतीत होते हैं (शायद जावा लोगों के रूप में ज्यादा नहीं है)।
sepp2k

7

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

उदाहरण के लिए, मैंने हाल ही में क्लोजर में एक खेल लिखा था, और खेल की पूरी स्थिति को एक अपरिवर्तनीय डेटा संरचना में परिभाषित किया गया था:

(def starting-game-state {:map ....
                          :player ....
                          :weather ....
                          :other-stuff ....}

और मुख्य गेम लूप को खेल राज्य में कुछ शुद्ध कार्यों को लूप में लागू करने के रूप में परिभाषित किया जा सकता है:

 (loop [initial-state starting-game-state]
   (let [user-input (get-user-input)
         game-state (update-game initial-state user-input)]
     (draw-screen game-state)
     (if-not (game-ended? game-state) (recur game-state))))

कहा जाने वाला प्रमुख कार्य है update-game, जो पिछले गेम स्टेट और कुछ यूजर इनपुट के लिए दिए गए सिमुलेशन स्टेप को चलाता है और नए गेम स्टेट को लौटाता है।

तो जटिलता कहां है? मेरे विचार में यह काफी अच्छी तरह से प्रबंधित किया गया है:

  • निश्चित रूप से अपडेट-गेम फ़ंक्शन बहुत काम करता है, लेकिन यह स्वयं अन्य कार्यों की रचना करके बनाया गया है, इसलिए यह वास्तव में एक बहुत ही सरल है। एक बार जब आप कुछ स्तरों पर चले जाते हैं, तो फ़ंक्शंस अभी भी बहुत सरल होते हैं, कुछ ऐसा करना जैसे "किसी ऑब्जेक्ट को मैप टाइल में जोड़ना"।
  • निश्चित रूप से खेल राज्य एक बड़ी डेटा संरचना है। लेकिन फिर, यह सिर्फ निचले स्तर की डेटा संरचनाओं की रचना करके बनाया गया है। इसके अलावा किसी भी तरीके की एम्बेडेड या वर्ग परिभाषा आवश्यक होने के बजाय यह "शुद्ध डेटा" है (यदि आप चाहें तो इसे एक बहुत ही कुशल अपरिवर्तनीय JSON ऑब्जेक्ट के रूप में सोच सकते हैं) तो बहुत कम बॉयलरप्लेट है।

OOP भी एनकैप्सुलेशन के माध्यम से जटिलता का प्रबंधन कर सकते हैं, लेकिन यदि आप OOP से इसकी तुलना करते हैं, तो कार्यात्मक के पास कुछ बहुत बड़े लाभ हैं:

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

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


2
मुझे लगता है कि लागू अपरिवर्तनीयता के कथित "लाभों" को प्रदर्शित करने के लिए एक खेल सबसे खराब संभव उदाहरणों में से एक है। चीजें लगातार एक खेल में घूम रही हैं, जिसका मतलब है कि आपको हर समय अपने खेल की स्थिति का पुनर्निर्माण करना है। और अगर सब कुछ अपरिवर्तनीय है, तो इसका मतलब है कि आपको न केवल खेल राज्य का पुनर्निर्माण करना है, बल्कि ग्राफ़ में वह सब कुछ है जो इसके लिए एक संदर्भ रखता है, या जो उस पर एक संदर्भ रखता है, और इसलिए पुनरावर्ती तक जब तक आप पूरे को रीसाइक्लिंग नहीं करते हैं। 30 + एफपीएस पर कार्यक्रम, बूट करने के लिए जीसी मंथन के टन के साथ! इससे अच्छा प्रदर्शन पाने का कोई तरीका नहीं है ...
मेसन व्हीलर

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

3
@Mason व्हीलर: वास्तव में, यह है लगभग बराबर पाने के लिए संभव अपरिवर्तनीय वस्तुओं के साथ प्रदर्शन, सब पर ज्यादा जीसी के बिना (उत्परिवर्तन के साथ के रूप में अच्छा के रूप में)। क्लोजर में चाल लगातार डेटा संरचनाओं का उपयोग कर रही है : वे अपरिवर्तनीय-से-प्रोग्रामर हैं, लेकिन वास्तव में हुड के तहत परस्पर योग्य हैं। दोनों ओर से लाभदायक।
जूनास पुलका

4
@quant_dev अधिक कोर बेहतर कोर से सस्ता है ... escapistmagazine.com/news/view/…
Deworde

6
@quant_dev - यह कोई बहाना नहीं है, यह एक गणितीय और वास्तुशिल्प तथ्य है कि आप एक बेहतर ओवरहेडिंग कर रहे हैं यदि आप कोर की संख्या के साथ अपने प्रदर्शन को लगभग रैखिक रूप से बढ़ाकर कर सकते हैं। कार्यात्मक भाषाएं अंततः बेहतर प्रदर्शन की पेशकश करेंगी क्योंकि हम एकल कोर प्रदर्शन के लिए लाइन के अंत में आ गए हैं, और यह सभी भविष्य में संगामिति और समानता के बारे में होगा। कार्यात्मक दृष्टिकोण (और विशेष रूप से अपरिवर्तनीयता) इस काम को बनाने में महत्वपूर्ण हैं।
मीका

3

"ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग एब्सट्रैक्शन का एक स्तर प्रदान करता है जो एक ही समय में एल्गोरिदम और डेटा पर लागू होता है, एक प्रकार का एब्सट्रैक्शन जो केवल कार्यात्मक अपघटन प्रदान नहीं करता है।"

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

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


1
मैंने "ओओ इन द लार्ज, एफपी इन द स्मॉल" कहीं - कहीं मुझे लगता है कि माइकल फेदर्स ने इसे उद्धृत किया है। मतलब, एफपी एक बड़े कार्यक्रम के विशेष हिस्सों के लिए अच्छा हो सकता है, लेकिन सामान्य तौर पर, यह ओओ होना चाहिए।
डैन

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

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

2

म्यूटेबल स्टेट, प्रोग्रामिंग और सॉफ्टवेयर / सिस्टम डिज़ाइन से संबंधित अधिकांश जटिलताओं और समस्याओं की जड़ है।

OO ने उत्परिवर्तनीय स्थिति को अपनाया। एफपी अभेद्य उत्परिवर्ती राज्य।

OO और FP दोनों के अपने उपयोग और स्वीट स्पॉट हैं। सोच के चुनें। और कहावत को याद रखें: "क्लोज़र गरीब आदमी की वस्तुएं हैं। वस्तुएं गरीब आदमी की करीबी हैं।"


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

1
@ दान: दिलचस्प है। मैंने वास्तव में बहुत अधिक विपरीत देखा है: एब्सट्रैक्शन के अधिक उपयोग से समस्याएँ उत्पन्न होती हैं, जिससे दोनों को समझना मुश्किल हो जाता है और जब आवश्यक हो, तब वास्तव में जो चल रहा होता है उसका विवरण ठीक करने के लिए।
मेसन व्हीलर

1

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

चलिए एक बहुत ही सरल उदाहरण लेते हैं। मान लीजिए कि ओरेकल ने फैसला किया है कि जावा स्ट्रिंग्स का एक रिवर्स तरीका होना चाहिए और आपने निम्नलिखित कोड लिखा है।

String x = "abc";
StringBuffer y = new StringBuffer(x);
y.reverse();
x.reverse();
x.toString().equals(y.toString());

अंतिम पंक्ति किसका मूल्यांकन करती है? आपको यह जानने के लिए स्ट्रिंग वर्ग के विशेष ज्ञान की आवश्यकता है कि यह गलत का मूल्यांकन करेगा।

क्या होगा अगर मैं अपनी खुद की कक्षा वूहोस्ट्रिंग बनाऊं

String x = "abc";
WuHoString y = new WuHoString(x);
y.reverse();
x.reverse();
x.toString().equals(y.toString())

यह जानना असंभव है कि अंतिम पंक्ति किसका मूल्यांकन करती है।

एक कार्यात्मक प्रोग्रामिंग शैली में इसे इस प्रकार अधिक लिखा जाएगा:

String x;
equals(toString(reverse(x)), toString(reverse(WuHoString(x))))

और यह सच होना चाहिए।

यदि सबसे बुनियादी वर्गों में से एक में 1 कार्य करना मुश्किल है, तो इसके बारे में तर्क करना मुश्किल है, अगर एक परिवर्तन योग्य वस्तुओं के इस विचार को शुरू करने से जटिलता बढ़ गई है या कम हो गई है।

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


3
यह थोड़ा अजीब है कि आप कहते हैं कि OO भाषाएँ अपरिवर्तनीय वस्तुओं के लिए नहीं बनाई गई हैं और फिर बाद में तार के साथ एक उदाहरण का उपयोग करें (जो जावा सहित अधिकांश OO- भाषाओं में अपरिवर्तनीय हैं)। इसके अलावा मुझे यह भी बताना चाहिए कि ओओ (या बहु-प्रतिमान) भाषाएँ हैं जिन्हें अपरिवर्तनीय वस्तुओं (उदाहरण के लिए स्काला) पर जोर देने के लिए डिज़ाइन किया गया है।
sepp2k

@ sepp2k: इसकी आदत डाल लें। एफपी अधिवक्ता हमेशा विचित्र, आकस्मिक उदाहरणों के आसपास फेंक रहे हैं जिनका वास्तविक दुनिया कोडिंग से कोई लेना-देना नहीं है। यह कोर एफपी अवधारणाओं को लागू करने का एकमात्र तरीका है जैसे कि लागू की गई अपरिवर्तनीयता अच्छी लगती है।
मेसन व्हीलर

1
@ मेसन: हुह? "जावा (और C #, अजगर, आदि) अपरिवर्तनीय स्ट्रिंग्स का उपयोग करने और यह बहुत अच्छा काम करता है"
sepp2k

1
@ sepp2k: अगर अपरिवर्तनीय स्ट्रिंग्स इतना बढ़िया काम करते हैं, तो StringBuilder / StringBuffer शैली की कक्षाएं क्यों दिखाई देती हैं? यह अपने तरीके से होने वाले अमूर्त उलटफेर का सिर्फ एक और उदाहरण है।
मेसन व्हीलर

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

0

मुझे लगता है कि ज्यादातर मामलों में क्लासिक ओओपी अमूर्त समवर्ती जटिलता को कवर नहीं करता है। इसलिए OOP (इसके मूल अर्थ से) FP को बाहर नहीं करता है, और इसीलिए हम scala जैसी चीजों को देखते हैं।


0

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

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

उदाहरण के लिए, मैं एक प्रोग्रामिंग भाषा पर काम कर रहा हूं, जिसे TPL कहा जाता है। बीजगणितीय डेटा प्रकार इसे बनाते हैं वास्तव में आसान मूल्यों का प्रतिनिधित्व करने के लिए:

data TPLValue = Null
              | Number Integer
              | String String
              | List [TPLValue]
              | Function [TPLValue] TPLValue
              -- There's more in the real code...

यह क्या कहता है - बहुत ही दृश्य तरीके से - यह है कि एक TPLValue (मेरी भाषा में कोई भी मूल्य) एक Nullया एक हो सकता हैNumber एक साथ Integerमूल्य या यहां तक कि एक Functionमूल्यों (पैरामीटर) की सूची के साथ और एक अंतिम मूल्य (शरीर )।

आगे मैं कुछ सामान्य व्यवहार को एनकोड करने के लिए टाइप क्लास का उपयोग कर सकता हूं। उदाहरण के लिए, मैं बना सकता हैTPLValue और उदाहरण के लिए Showजिसका अर्थ है कि इसे एक स्ट्रिंग में परिवर्तित किया जा सकता है।

इसके अतिरिक्त, मैं अपनी स्वयं की प्रकार की कक्षाओं का उपयोग कर सकता हूं, जब मुझे कुछ प्रकारों के व्यवहार को निर्दिष्ट करने की आवश्यकता होती है (जिनमें मैं खुद को लागू नहीं करता हूं)। उदाहरण के लिए, मेरे पास एक Extractableप्रकार का वर्ग है जो मुझे एक फ़ंक्शन लिखने देता है जो TPLValueएक उपयुक्त लेता है और एक उपयुक्त सामान्य मान देता है। इस प्रकार extractएक में बदल सकते हैं Numberएक करने के लिए Integerया एक Stringएक करने के लिए Stringजब तकInteger और Stringके उदाहरण हैं Extractable

अंत में, मेरे कार्यक्रम का मुख्य तर्क कई कार्यों में है जैसे evalऔरapply । ये वास्तव में मूल हैं - वे TPLValueएस लेते हैं और उन्हें अधिक TPLValueएस में बदल देते हैं , साथ ही साथ राज्य और त्रुटियों को संभालते हैं।

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


हाँ, प्यार होगा eval। "अरे, मुझे देखो! मुझे अपने सुरक्षा छेद लिखने की आवश्यकता नहीं है; मुझे प्रोग्रामिंग भाषा में बनाया गया एक मनमाना कोड निष्पादन भेद्यता मिली है !" कोड के साथ डेटा का संघर्ष, सभी समय की सुरक्षा कमजोरियों के दो सबसे लोकप्रिय वर्गों में से एक है। जब भी आप किसी को SQL इंजेक्शन के हमले (कई अन्य चीजों के बीच) के कारण हैक करते हुए देखते हैं, क्योंकि कुछ प्रोग्रामर को पता नहीं है कि कोड से डेटा को ठीक से कैसे अलग किया जाए।
मेसन व्हीलर

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

3
हाँ, मैंने सुना है "मैक्रोज़ कमाल हैं" पहले कई बार बात करते हैं। लेकिन मैंने कभी भी लिस्प मैक्रो का वास्तविक उदाहरण नहीं देखा है जो कि कुछ कर रहा है 1) व्यावहारिक है और कुछ आप वास्तव में वास्तविक दुनिया कोड में करने के लिए देखभाल करेंगे और 2) कार्यों का समर्थन करने वाली किसी भी भाषा में आसानी से पूरा नहीं किया जा सकता है।
मेसन व्हीलर

1
@MasonWheeler शॉर्ट-सर्किटिंग and। छोटी-मोटी परिक्रमा orletlet-recconddefn। इनमें से किसी को भी लागू नहीं किया जा सकता है। for(सूची समझ)। dotimesdoto

1
@ मेटफ़ेनविक: ठीक है, मुझे वास्तव में अपने दो से ऊपर एक तीसरा बिंदु जोड़ना चाहिए: 3) पहले से ही किसी भी प्रोग्रामिंग भाषा के लिए अंतर्निहित नहीं है क्योंकि यह एकमात्र वास्तविक उपयोगी मैक्रो उदाहरण है जो मैं कभी भी देखता हूं, और जब आप कहते हैं "अरे मुझे देखो, मेरी भाषा इतनी लचीली है कि मैं अपने शॉर्ट-सर्किट को लागू कर सकता हूं and!" मैंने सुना, "अरे मुझे देखो, मेरी भाषा इतनी अपंग है कि यह एक छोटी-सी परिधि के साथ भी नहीं आती है andऔर मुझे हर चीज के लिए पहिया को सुदृढ़ करना होगा !"
मेसन व्हीलर

0

उद्धृत वाक्य की अब कोई वैधता नहीं है, जहां तक ​​मैं देख सकता हूं।

समकालीन OO भाषाएँ उन प्रकारों पर अमूर्त नहीं कर सकती हैं जिनकी तरह * नहीं है, अर्थात उच्चतर प्रकार के अज्ञात हैं। उनकी प्रकार प्रणाली "कुछ तत्वों के साथ कंटेनर, जो तत्वों पर एक फ़ंक्शन को मैप करने की अनुमति देता है" के विचार को व्यक्त करने की अनुमति नहीं देता है।

इसलिए, हास्केल्स की तरह यह मूल कार्य

fmap :: Functor f => (a -> b) -> f a -> f b 

जावा *) में आसानी से नहीं लिखा जा सकता है, उदाहरण के लिए, कम से कम एक प्रकार से सुरक्षित तरीके से नहीं। इसलिए, बुनियादी कार्यक्षमता प्राप्त करने के लिए, आपको बहुत सारे बॉयलरप्लेट लिखना होगा, क्योंकि आपको आवश्यकता है

  1. एक सूची के तत्वों के लिए एक सरल कार्य लागू करने के लिए एक विधि
  2. एक सरणी के तत्वों के लिए एक ही सरल कार्य लागू करने के लिए एक विधि
  3. हैश के मानों में समान सरल फ़ंक्शन को लागू करने की एक विधि,
  4. .... सेट
  5. .... पेड़
  6. ... 10. उसी के लिए इकाई परीक्षण

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

  1. सूची, एरे, मैप, सेट और ट्री के लिए एक फ़ंक्टर उदाहरण (ज्यादातर पूर्वनिर्धारित, या कंपाइलर द्वारा स्वचालित रूप से प्राप्त किया जा सकता है)
  2. सरल कार्य

ध्यान दें कि यह जावा 8 के साथ बदलने वाला नहीं है (बस यह है कि कोई व्यक्ति अधिक आसानी से फ़ंक्शन लागू कर सकता है, लेकिन फिर, वास्तव में, उपरोक्त सामग्री के ऊपर समस्या होगी। जब तक आपके पास उच्च कार्य फ़ंक्शन नहीं होते हैं, तो आप सबसे अधिक संभावना भी नहीं हैं। यह समझने में सक्षम है कि उच्च प्रकार के प्रकार किसके लिए अच्छे हैं।)

यहां तक ​​कि सीलोन जैसी नई ओओ भाषाओं में उच्च प्रकार के प्रकार नहीं हैं। (मैंने हाल ही में गैविन किंग से पूछा है, और उन्होंने मुझे बताया, यह इस समय महत्वपूर्ण नहीं था।) हालांकि कोटलिन के बारे में नहीं जानते, हालांकि।

*) निष्पक्ष रहने के लिए, आपके पास एक इंटरफ़ेस फ़ंक्टर हो सकता है जिसमें एक विधि फ़ैप है। बुरी बात यह है कि आप यह नहीं कह सकते हैं: अरे, मैं जानता हूं कि लाइब्रेरी क्लास सुपरकंक्रिटब्लॉकडब्लडडीड लाइकडेकहैसपावर के लिए फैप को कैसे लागू किया जाता है, प्रिय कंपाइलर, कृपया स्वीकार करें कि अब से, सभी सुपरकंट्रेक्टल बब्लडडाउल्डलीडेकडेकहाईसैप्स फंक्शंस हैं।


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

-2

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

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

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


2
प्रोग्रामर्स में आपका स्वागत है। कृपया अपने उत्तर में बयानबाजी को कम करने और बाहरी संदर्भों के साथ अपने कुछ दावों का समर्थन करने पर विचार करें।

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