2012-08-24 16 views
8

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

  1. रेफरी के बीच संबंध क्या है। पारदर्शिता और अपरिवर्तनीयता। क्या कोई दूसरे का तात्पर्य करता है?

  2. कभी-कभी साइड इफेक्ट्स और अपरिवर्तनीयता का उपयोग एक दूसरे के लिए किया जाता है। क्या यह सही है?

+0

आप "बेवकूफता" भी भूल गए: पी – mergeconflict

उत्तर

2

पहले के लिए "नहीं" पहला - एक दूसरे का तात्पर्य है, लेकिन विपरीत नहीं है, और दूसरे के लिए एक योग्य "हां" है।

  1. "An expression is said to be referentially transparent if it can be replaced with its value without changing the behavior of a program"। अपरिवर्तनीय इनपुट से पता चलता है कि एक अभिव्यक्ति (फ़ंक्शन) हमेशा एक ही मान पर मूल्यांकन करेगी, और इसलिए संदर्भित पारदर्शी हो।

    हालांकि, (mergeconflict कृपया मुझे इस मुद्दे पर सही कर गया है) किया जा रहा है referentially पारदर्शी जरूरी अचल स्थिति आवश्यकता नहीं है।

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

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

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

+0

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

+0

@mergeconflict सुधार के लिए धन्यवाद, और आपकी प्रतिक्रिया में विवरण! उत्तर तदनुसार समायोजित करें। –

1

यह बल्कि विशिष्ट परिभाषा आप (असहमति, वहाँ हो सकता है, उदाहरण के लिए Purity vs Referential transparency देखें) का उपयोग पर निर्भर करता है, लेकिन मुझे लगता है कि यह एक उचित व्याख्या है:

Referential पारदर्शिता और 'पवित्रता' कार्य/भाव के गुणों कर रहे हैं । एक फ़ंक्शन/अभिव्यक्ति दुष्प्रभाव हो सकती है या नहीं हो सकती है। दूसरी ओर, अपरिवर्तनीयता, वस्तुओं की एक संपत्ति है, कार्य/अभिव्यक्ति नहीं।

संदर्भित पारदर्शिता, साइड इफेक्ट्स और शुद्धता निकटता से संबंधित हैं: 'शुद्ध' और 'संदर्भित पारदर्शी' बराबर हैं, और ये धारणा दुष्प्रभावों की अनुपस्थिति के बराबर हैं।

एक अपरिवर्तनीय वस्तु में विधियों को पारदर्शी रूप से पारदर्शी नहीं किया जा सकता है: वे विधियां ऑब्जेक्ट को स्वयं नहीं बदलेगी (क्योंकि यह ऑब्जेक्ट को व्यवहार्य बनाती है), लेकिन अन्य दुष्प्रभाव हो सकते हैं जैसे I/O प्रदर्शन करना या उनका उपयोग करना (परिवर्तनीय) पैरामीटर।

8

इस प्रश्न में कुछ विशेष रूप से नाइट-पिक्य उत्तरों की आवश्यकता है, क्योंकि यह सामान्य शब्दावली को परिभाषित करने के बारे में है।

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

object Ex0 { 
    def +(x: Int, y: Int): Int = x + y 
} 

x और y के लिए कोई मान को देखते हुए स्पष्ट रूप से + हमेशा एक ही परिणाम का उत्पादन करेगा। यह एक समारोह है। यदि कंपाइलर अतिरिक्त चालाक था, तो यह इनपुट की प्रत्येक जोड़ी के लिए इस फ़ंक्शन के परिणामों को कैश करने के लिए कोड डाल सकता है, और एक कैश लुकअप को ऑप्टिमाइज़ेशन के रूप में निष्पादित करता है। यह यहां स्पष्ट रूप से सुरक्षित है।

समस्या यह है कि सॉफ़्टवेयर में, "फ़ंक्शन" शब्द का कुछ हद तक दुर्व्यवहार किया गया है: हालांकि कार्य तर्क स्वीकार करते हैं और उनके हस्ताक्षर में घोषित मूल्यों को वापस करते हैं, वे कुछ बाहरी संदर्भ को भी पढ़ और लिख सकते हैं। उदाहरण के लिए:

class Ex1 { 
    def +(x: Int): Int = x + Random.nextInt 
} 

हम अब और एक गणितीय समारोह के रूप में इस के बारे में सोच नहीं सकते, क्योंकि x, + की दी गई मूल्य एक यादृच्छिक मूल्य है, जो कहीं दिखाई नहीं देता है के आधार पर अलग परिणाम उत्पन्न कर सकते (के लिए + का हस्ताक्षर)। ऊपर वर्णित अनुसार + का परिणाम सुरक्षित रूप से कैश नहीं किया जा सकता है। तो अब हमारे पास एक शब्दावली समस्या है, जिसे हम कहकर हल करते हैं कि Ex0.+शुद्ध, और Ex1.+ नहीं है।

ठीक है, क्योंकि अब हमने कुछ हद तक अशुद्धता स्वीकार कर ली है, हमें यह परिभाषित करने की आवश्यकता है कि हम किस तरह की अशुद्धता के बारे में बात कर रहे हैं! इस मामले में, हम जो बोलते हैं उसे अंतर यह है कि हम कैश कर सकते Ex0.+ है 'अपनी आदानों x और y के साथ जुड़े परिणाम है, और है कि हम कर सकते हैं कैश Ex1.+ नहीं' अपने इनपुट x के साथ जुड़े s परिणाम। शब्द जिसे हम कैशबिलिटी का वर्णन करने के लिए उपयोग करते हैं (या, अधिक उचित रूप से, इसके आउटपुट के साथ फ़ंक्शन कॉल की प्रतिस्थापन) रेफरेंसियल पारदर्शिता है।

सभी शुद्ध कार्य संदर्भित पारदर्शी हैं, लेकिन कुछ संदर्भित पारदर्शी कार्य शुद्ध नहीं हैं। उदाहरण के लिए:

object Ex2 { 
    var lastResult: Int 
    def +(x: Int, y: Int): Int = { 
    lastResult = x + y 
    lastResult 
    } 
} 

यहाँ हम किसी भी बाहरी संदर्भ से पढ़ नहीं कर रहे हैं, और किसी भी आदानों x और y के लिए Ex2.+ द्वारा उत्पादित मूल्य हमेशा संचित करने योग्य हो जाएगा, Ex0 में के रूप में। यह संदर्भित रूप से पारदर्शी है, लेकिन इसमें साइड इफेक्ट है, जो फ़ंक्शन द्वारा गणना की गई अंतिम मान को संग्रहीत करना है। कोई और बाद में आ सकता है और lastResult पकड़ सकता है, जो उन्हें Ex2.+ के साथ क्या हो रहा है में कुछ चुस्त अंतर्दृष्टि देगा!

एक ओर ध्यान दें: आप यह भी तर्क कर सकते हैं कि Ex2.+नहीं referentially पारदर्शी है, क्योंकि यद्यपि कैशिंग समारोह के परिणाम के संबंध में सुरक्षित है, पक्ष प्रभाव चुपचाप एक कैश के मामले में नजरअंदाज कर दिया है " मारो।" दूसरे शब्दों में, यदि कैश प्रभाव महत्वपूर्ण है (इसलिए Norman Ramsey's comment) कैश शुरू करना प्रोग्राम का अर्थ बदलता है, तो! यदि आप इस परिभाषा को प्राथमिकता देते हैं, तो संदर्भित पारदर्शी होने के लिए एक फ़ंक्शन शुद्ध होना चाहिए।

अब, यहाँ का पालन करने के एक बात यह है कि अगर हम एक ही जानकारी के साथ एक पंक्ति में दो बार या उससे अधिक Ex2.+ फोन, lastResult परिवर्तन नहीं होगा है। विधि n बार का आह्वान करने का दुष्प्रभाव केवल एक बार विधि को आमंत्रित करने के दुष्प्रभाव के बराबर है, और इसलिए हम कहते हैं कि Ex2.+idempotent है। अब, हर बार जब हम फोन Ex3.+, इतिहास परिवर्तन

object Ex3 { 
    var history: Seq[Int] 
    def +(x: Int, y: Int): Int = { 
    result = x + y 
    history = history :+ result 
    result 
    } 
} 

, इसलिए समारोह अब idempotent है: हम यह बदल सकता है।

ठीक है, अब तक एक रिकैप: शुद्ध फ़ंक्शन वह है जो न तो किसी भी बाहरी संदर्भ से पढ़ता है और न ही लिखता है। यह दोनों अलग-अलग पारदर्शी और साइड इफेक्ट मुक्त दोनों है। कुछ बाहरी संदर्भ से पढ़ता एक फ़ंक्शन अब संदर्भित पारदर्शी नहीं होता है, जबकि कुछ बाहरी संदर्भ में लिखने वाला फ़ंक्शन साइड इफेक्ट्स से मुक्त नहीं होता है। और आखिरकार, एक फ़ंक्शन जिसे एक ही इनपुट के साथ कई बार बुलाया जाता है, वही दुष्प्रभाव होता है जिसे इसे केवल एक बार कॉल किया जाता है, जिसे idempotent कहा जाता है। ध्यान दें कि बिना किसी दुष्प्रभाव वाले फ़ंक्शन, जैसे कि शुद्ध फ़ंक्शन, भी बेवकूफ है!

तो कैसे करता है अस्थिरता और यह सब में अचल स्थिति खेलने? खैर, Ex2 और Ex3 पर वापस देखें। वे mutable var एस परिचय। Ex2.+ और Ex3.+ के साइड इफेक्ट्स उनके संबंधित var एस को म्यूटेट करना है! तो उत्परिवर्तन और दुष्प्रभाव हाथ में आते हैं; एक फ़ंक्शन जो केवल अपरिवर्तनीय डेटा पर चल रहा है, दुष्प्रभाव मुक्त होना चाहिए। यह अभी भी शुद्ध नहीं हो सकता है (यानी, यह संदर्भित रूप से पारदर्शी नहीं हो सकता है), लेकिन कम से कम यह साइड इफेक्ट्स का उत्पादन नहीं करेगा।

इस पर एक तार्किक अनुवर्ती प्रश्न हो सकता है: "शुद्ध कार्यात्मक शैली के क्या फायदे हैं?" उस प्रश्न का उत्तर अधिक शामिल है;)

+0

'शुद्ध' का बहुत अच्छा विवरण, इसके लिए धन्यवाद। मैं रेफरेंसियल पारदर्शिता के संबंध में आपके उदाहरण 'Ex2' से असहमत हूं, हालांकि: यह दुष्प्रभाव शेष कार्यक्रम के लिए दृश्यमान है (क्योंकि यह' lastResult' पढ़ सकता है), जिसका अर्थ है उदाहरण के लिए इस विधि को ज्ञापन लागू करने से परिणाम बदल जाएगा/कार्यक्रम के देखने योग्य व्यवहार। यह इस विधि को संदर्भित रूप से पारदर्शी नहीं बनाता है - मुझे किसी भी परिभाषा के बारे में पता नहीं है जो असहमत है। –

+0

ग्रे क्षेत्र जो आप सोच रहे हैं वह एक निजी कैश है, जो शेष कार्यक्रम के लिए सुलभ नहीं है: एक विधि जो इस तरह के कैश में मध्यवर्ती परिणाम संग्रहीत करती है, का दुष्प्रभाव होता है (कैश भरना), लेकिन आवेदन करना ज्ञापन कार्यक्रम के नतीजे को नहीं बदलता है। चाहे ऐसी विधि को 'रेफरेंशियल पारदर्शी' माना जाता है, वास्तव में बहस योग्य है। –

+0

@ArnoutEngelen पहले से ही कहा गया है, यह थोड़ा उलझन में है कि आप संदर्भित पारदर्शी <-> साइड इफेक्ट्स के साथ क्या मतलब है। क्या आप एक उदाहरण प्रदान कर सकते हैं जो पारदर्शी रूप से पारदर्शी है लेकिन इसका कोई दुष्प्रभाव नहीं है और शुद्ध नहीं है? – sschaef

संबंधित मुद्दे