क्या एक फ़ंक्शन तुरंत अशुद्ध है अगर यह एक फ़ंक्शन को पैरामीटर के रूप में लेता है?


17

चूंकि रनटाइम तक एक इनपुट पैरामीटर की शुद्धता अज्ञात है, क्या एक फ़ंक्शन तुरंत अशुद्ध माना जाता है अगर यह एक फ़ंक्शन पैरामीटर को इनपुट पैरामीटर के रूप में लेता है?

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

संदर्भ के लिए, मैं जावास्क्रिप्ट में कार्यात्मक कोड लिख रहा हूं।


एक तुच्छ काउंटर उदाहरण के रूप में, विचार करें:foo = function(function bar){ print(bar.toString()) }
डेविड ने कहा कि मोनिका

1
@DavidGrinberg यह एक काउंटर उदाहरण नहीं है, मुझे लगता है, और वास्तव में एक बड़ा मुद्दा उजागर करता है; यदि आपके पास ऐसे कार्य हैं जिन्हें ओवरराइड किया जा सकता है, और यह गारंटी नहीं दे सकता है कि कार्यान्वयन साइड-इफ़ेक्ट फ्री हैं, तो आप गारंटी नहीं दे सकते हैं कि अधिकांश फ़ंक्शन जो ऑब्जेक्ट लेते हैं और उनके तरीकों को कॉल करते हैं वे या तो शुद्ध हैं। हो सकता है कि बार की स्ट्रैसिंग () डिस्क से कुछ फाइलों को हटा दे?
जोशुआ टेलर 19

3
@DavidGrinberg लेकिन, मुझे लगता है कि आप एक अच्छी दिशा में सोच रहे हैं। foo = function(function bar) { return 3; } है शुद्ध, और एक तर्क के रूप में एक समारोह लेता है।
जोशुआ टेलर 19

@JoshuaTaylor फेयर पॉइंट, मैंने ऐसा नहीं सोचा था। लेकिन आप पहले से ही समस्या को हल कर चुके हैं। वैकल्पिक फिक्स के रूप में, बस 'रूट' toString()(यानी आप जावा के ऑब्जेक्ट पर पाएंगे) को कॉल करें ।
डेविड का कहना है कि

जवाबों:


22

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

आउटपुट जो प्रत्येक बार समान इनपुट के लिए समान होता है, यह नियंत्रित करता है कि पैरामीटर शुद्ध हैं या नहीं। यदि आप मान लेते हैं कि पैरामीटर (एक फ़ंक्शन तर्क की तरह) भी शुद्ध हैं, तो यह शुद्ध है।

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

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

व्यवहार में मेरे अनुभव में यह आमतौर पर एक बड़ी बात नहीं है - मुझे लगता है कि शुद्ध कार्यों के लिए तर्क तर्कों के रूप में अशुद्ध कार्यों का उपयोग किया जाना दुर्लभ है।


आपके कथन के बारे में कि "जब तक फ़ंक्शन में उपयोग किए जाने वाले सभी मान पूरी तरह से इसके मापदंडों से परिभाषित होते हैं, यह एक शुद्ध कार्य है"। स्थिरांक के मामले में क्या होता है? यदि मेरे पास कोई फ़ंक्शन है areaOfCircle r => Math.Pi * r * r, areaOfCircleतो क्या यह गैर-शुद्ध होगा क्योंकि यह सिर्फ मापदंडों का उपयोग नहीं करता है?
डेविड अरनो

2
@DavidArno यह एक उचित बिंदु है। संदर्भात्मक पारदर्शिता के अनुसार, स्थैतिक बाहर मूल्य का जिक्र इसे हार्डकोड किए जाने से अलग नहीं होगा, इसलिए यह अभी भी शुद्ध होगा।
डेनिथ

1
"इसका मतलब है कि शुद्ध कार्य करने के लिए अशुद्ध व्यवहार करना संभव है" - परिभाषा के अनुसार, शुद्ध कार्य में अशुद्ध व्यवहार नहीं हो सकता है। आप एक समारोह में सोच की गलती कर रहे हैं f(f2)कि आह्वान f2संक्रामक कुछ भी पर निर्भर नहीं करता f2पर निर्भर करता है। एक फ़ंक्शन जो मनमाने ढंग से पारित किए गए कार्यों को लागू कर सकता है वह शुद्ध नहीं है।
user2357112

2
@ डैनिथ: बेहतर है, लेकिन यह अभी भी मानता है कि फ़ंक्शन को पास-इन फ़ंक्शन को लागू करना है। यह कुछ ऐसा हो सकता है function compose(f, g) {return function h(x) {return f(g(x));};}, जो तर्कों के रूप में कार्य करने के बावजूद शुद्ध है।
user2357112

1
"मुझे लगता है कि शुद्ध कार्यों के लिए तर्कों के रूप में अशुद्ध कार्यों का उपयोग करना दुर्लभ है।" - एक कार्यात्मक भाषा नहीं है, लेकिन कुछ C ++ लाइब्रेरी फ़ंक्शंस में विशिष्ट चेतावनियाँ हैं जो तर्क को विधेय करती हैं (कुछ सन्निकटन से) शुद्ध होना चाहिए। तो एक अर्थ में यह दुर्लभ नहीं है, यह कभी मान्य नहीं होता है। लेकिन एक अन्य अर्थ में उन्हें इस तथ्य से मना करना होगा क्योंकि लोग कभी-कभी ऐसा करना चाहते हैं। उदाहरण के लिए, वे एक findदिनचर्या पास करना चाहते हैं एक अशुद्ध विधेय जो तीसरे मिलान वाले आइटम के लिए "सच" लौटाता है, या कुछ ऐसी बकवास।
स्टीव जेसप

19

चूंकि रनटाइम तक एक इनपुट पैरामीटर की शुद्धता अज्ञात है, क्या एक फ़ंक्शन तुरंत अशुद्ध माना जाता है अगर यह एक फ़ंक्शन पैरामीटर को इनपुट पैरामीटर के रूप में लेता है?

नहीं

function pure(other_function) {
    return 1;
}

इससे कोई फर्क नहीं पड़ता है कि other_functionशुद्ध कार्य, अशुद्ध कार्य, या फ़ंक्शन नहीं है। pureसमारोह शुद्ध है।

अन्य प्रतिधारण:

function identity(x) {
    return x;
}

यह फ़ंक्शन शुद्ध है, भले ही xएक अशुद्ध फ़ंक्शन हो। identity(impure_function)हमेशा impure_functionकोई भी बात नहीं, चाहे आप कितनी भी बार कॉल दोहराएं। इससे कोई फर्क नहीं पड़ता कि क्या identity(impure_function)()हमेशा एक ही चीज वापस मिलती है; एक फ़ंक्शन का रिटर्न वैल्यू रिटर्न रिटर्न इसकी शुद्धता को प्रभावित नहीं करता है।


सामान्य तौर पर, यदि कोई फ़ंक्शन किसी फ़ंक्शन को कॉल कर सकता है तो उसे एक तर्क के रूप में पारित किया गया था, यह शुद्ध नहीं है। उदाहरण के लिए, एक फ़ंक्शन function call(f) {f();}शुद्ध नहीं है, क्योंकि भले ही यह किसी भी वैश्विक या उत्परिवर्तनीय स्थिति का उल्लेख नहीं करता है, लेकिन ऐसा fकुछ हो सकता है जो alertदृश्य साइड इफेक्ट का कारण बनता है।

यदि कोई फ़ंक्शन तर्कों के रूप में कार्य करता है, लेकिन यह उन्हें कॉल नहीं करता है या उन्हें कॉल करने का कारण बनता है, तो यह शुद्ध हो सकता है। यह अभी भी अशुद्ध हो सकता है अगर यह कुछ अन्य अशुद्ध काम करता है। उदाहरण के लिए, function f(ignored_function) {alert('This isn't pure.');}अशुद्ध है, भले ही यह कभी भी फोन न करे ignored_function


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

13
@walpen: सवाल तर्क को लागू करने का कोई उल्लेख नहीं करता है। प्रश्नकर्ता को यह मानने का कोई कारण नहीं है कि एक फ़ंक्शन को यह महसूस किए बिना कि एक फ़ंक्शन को इनपुट के रूप में कोई अन्य फ़ंक्शन ले सकता है। इस तरह छिपी हुई धारणाओं को इंगित करना महत्वपूर्ण है, बजाय इसके कि आप उन्हें ग्रहण करने के लिए बने थे।
user2357112

12

चूंकि रनटाइम तक एक इनपुट पैरामीटर की शुद्धता अज्ञात है, क्या एक फ़ंक्शन तुरंत अशुद्ध माना जाता है अगर यह एक फ़ंक्शन पैरामीटर को इनपुट पैरामीटर के रूप में लेता है?

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

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

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

वे उपयोगी गुण अभी भी धारण करते हैं यदि फ़ंक्शन अपने काम को करने के लिए अन्य शुद्ध रीड-ओनली फ़ंक्शन का उपयोग करता है, भले ही यह उनके संदर्भ में कैसे भी हो।


5

जैसा कि टेलस्टीन ने कहा: तकनीकी रूप से, हाँ, जब तक कि आपकी भाषा में कोई तरीका नहीं है, यह गारंटी देने के लिए कि इनपुट फ़ंक्शन भी शुद्ध है।

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

ऐसा शुद्ध ~ फंक्शन जिसे आप जावास्क्रिप्ट में लिखेंगे

function foo(f) {
   return f(1) + 2;
}

हास्केल को सीधे अनुवाद किया जा सकता है:

foo :: (Int -> Int) -> Int
foo f = f 1 + 2

अब, जावास्क्रिप्ट में आप जैसे बुराई सामान कर सकते हैं

js> foo (function(x) {console.log("muharhar"); return 0})
muharhar
2

हास्केल में यह संभव नहीं है । कारण, कुछ साइड-इफ़ेक्ट-फुल जैसे console.log()हमेशा एक परिणाम प्रकार होना चाहिए IO something, न कि केवल somethingअकेले।

GHCi> foo (\x -> print "muarhar" >> return 0)

<interactive>:7:12:
    Couldn't match expected type ‘Int’ with actual type ‘IO b0’
    In the expression: print "muarhar" >> return 0
    In the first argument of ‘foo’, namely
      ‘(\ x -> print "muarhar" >> return 0)’
    In the expression: foo (\ x -> print "muarhar" >> return 0)

इस अभिव्यक्ति को टाइप करने के लिए, हमें fooटाइप सिग्नेचर देना होगा

foo :: (Int -> IO Int) -> Int

लेकिन यह पता चला है कि मैं इसे अब और लागू नहीं कर सकता: क्योंकि तर्क फ़ंक्शन के IOपरिणाम में है, मैं इसका उपयोग नहीं कर सकता foo

<interactive>:8:44:
    Couldn't match expected type ‘Int’ with actual type ‘IO Int’
    In the first argument of ‘(+)’, namely ‘f 1’
    In the expression: f 1 + 2

एक ही रास्ता मैं एक इस्तेमाल कर सकते हैं IOमें कार्रवाई fooहै यदि का परिणाम fooटाइप है IO Intही:

foo :: (Int -> IO Int) -> IO Int
foo f = do
   f1 <- f 1
   return (f1 + 2)

लेकिन इस बिंदु पर यह स्पष्ट है fooकि यह एक शुद्ध कार्य नहीं है।


1
इससे पहले कि आप "असंभव" कहते हैं, unsafeIO:-)
बरगी

2
@Bergi: यह वास्तव में हास्केल का हिस्सा नहीं है, लेकिन इसके विदेशी फ़ंक्शन इंटरफ़ेस का: यह दावा करने की अनुमति देने के लिए कि किसी अन्य भाषा में परिभाषित एक फ़ंक्शन शुद्ध है, जो हास्केल संकलक स्पष्ट रूप से टाइप हस्ताक्षर से अनुमान नहीं लगा सकता है क्योंकि अन्य भाषाएं आमतौर पर नहीं हैं के रूप में ऐसी बात IO। संयोग से, इसका उपयोग "शुद्ध" फ़ंक्शन में साइड-इफ़ेक्ट छिपाकर तबाही मचाने के लिए किया जा सकता है, लेकिन यह वास्तव में हास्केल में असुरक्षित है क्योंकि शुद्ध कार्यों के मूल्यांकन क्रम को निर्दिष्ट करने के लिए वास्तव में एक विश्वसनीय तरीका नहीं है।
लेफ्टरेंबाउट

हाँ यह सच है। हालांकि, मुझे लगता है कि मैंने इसका उपयोग "शुद्ध" फ़ंक्शन के साथ-साथ लाभकारी दुष्प्रभावों को "छिपाने" के लिए भी किया है, जहां दृष्टिकोण की सुरक्षा पहले स्थापित की जानी थी।
बर्गी

@Bergi आप ज्यादातर उपयोग नहीं करना चाहिए unsafeIO; यह एक अंतिम उपाय हैच हैच है जो सिस्टम की गारंटी देता है, और इसलिए आपका एक अच्छा बिंदु नहीं है।
एंड्रेस एफ।

0

नहीं ऐसा नहीं है।

यदि पारित फ़ंक्शन अशुद्ध है और आपका फ़ंक्शन पारित फ़ंक्शन को कॉल करता है, तो आपके फ़ंक्शन को अशुद्ध माना जाएगा।

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


यह उत्तर कुछ भी नहीं जोड़ता है जो पहले से ही इस एक में नहीं बताया गया है ... कृपया चीजों को बहाल करने से पहले पूर्व उत्तर की समीक्षा करें :)
एंड्रेस एफ।

क्या सिंक / async सादृश्य के बारे में?
बॉबी मारिनॉफ
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.