इस प्रश्न में कुछ विशेष रूप से नाइट-पिक्य उत्तरों की आवश्यकता है, क्योंकि यह सामान्य शब्दावली को परिभाषित करने के बारे में है।
पहला, फ़ंक्शन इनपुट के "डोमेन" और आउटपुट के "श्रेणी" (या कोडोमेन) के बीच गणितीय संबंध का एक प्रकार है। प्रत्येक इनपुट एक स्पष्ट उत्पादन पैदा करता है। उदाहरण के लिए, पूर्णांक अतिरिक्त फ़ंक्शन +
डोमेन 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
एस को म्यूटेट करना है! तो उत्परिवर्तन और दुष्प्रभाव हाथ में आते हैं; एक फ़ंक्शन जो केवल अपरिवर्तनीय डेटा पर चल रहा है, दुष्प्रभाव मुक्त होना चाहिए। यह अभी भी शुद्ध नहीं हो सकता है (यानी, यह संदर्भित रूप से पारदर्शी नहीं हो सकता है), लेकिन कम से कम यह साइड इफेक्ट्स का उत्पादन नहीं करेगा।
इस पर एक तार्किक अनुवर्ती प्रश्न हो सकता है: "शुद्ध कार्यात्मक शैली के क्या फायदे हैं?" उस प्रश्न का उत्तर अधिक शामिल है;)
आप "बेवकूफता" भी भूल गए: पी – mergeconflict