Println को अशुद्ध कार्य क्यों माना जाता है?


10

मैं स्कैला में पुस्तक प्रोग्रामिंग पढ़ रहा हूं, और यह कहा जाता है:

... इस मामले में, इसका दुष्प्रभाव मानक आउटपुट स्ट्रीम पर प्रिंट हो रहा है।

और मैं नहीं दिख रहा है जहां, पक्ष प्रभाव है, के बाद से ही इनपुट के लिए, println ही निर्गम (मुझे लगता है कि) प्रिंट होगा
अद्यतन
उदाहरण के लिए किसी भी समय हम कहते हैं:

println(5)

यह 5 प्रिंट करेगा , मुझे ऐसा मामला नहीं दिखाई println(5)देगा जहां कॉलिंग 5 के अलावा एक मूल्य प्रिंट करेगी !!


यदि यह आपके प्रश्न का उत्तर देता है, तो मैं अपना उत्तर सॉफ्टवेयरइंजीनियरिंग.स्टैकएक्सचेंज.
com

3
पर जवाब क्या निर्देशात्मक पारदर्शिता है? यहां प्रासंगिक लगते हैं।
नाथन ह्यूजेस

1
संबंधित (योग्य) stackoverflow.com/q/4865616/5986907
joelb

2
आपने नियतात्मक के साथ साइड इफ़ेक्ट (रेफरेंशियल ट्रांसपेरेंट नहीं) को भ्रमित किया। printlnएक नियतात्मक कार्य है लेकिन शुद्ध होने के लिए यह आरटी भी होना चाहिए।
बॉब

2
क्योंकि यह एक परिणाम की गणना के अलावा कुछ और करता है और इसे वापस करता है।
सेठ टिस्यू

जवाबों:


6

आप बता सकते हैं कि अभिव्यक्ति को उसके परिणाम के साथ बदलने से कोई साइड इफेक्ट होता है या नहीं। यदि प्रोग्राम का अर्थ बदल जाता है , तो इसका साइड इफेक्ट है। उदाहरण के लिए,

println(5)

के लिए एक अलग कार्यक्रम है

()

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


6
वास्तव में यह "साइड-इफ़ेक्ट" की अच्छी परिभाषा नहीं है - एक साइड इफ़ेक्ट को ऐसी किसी भी चीज़ के रूप में परिभाषित किया जा सकता है जो संदर्भात्मक पारदर्शिता को तोड़ती है। आपने यहां जो दिखाने की कोशिश की वह RT था लेकिन आपका उदाहरण गलत है। चूँकि किसी चीज को निष्पादित करने के लिए एक ही बार में कई बार म्यूटेंट टाइम val a = println("hello"); val b = (a, a)करना चाहिए - बल्कि, जैसा होना चाहिए val b = (pritnln("hello"), println("hello"))
लुइस मिगुएल मेजा सुआरेज़

1
@ LuisMiguelMejíaSuárez शायद मेरा उदाहरण स्पष्ट नहीं है, लेकिन मुझे नहीं लगता कि यह गलत है। मैं अनिवार्य रूप से कार्यक्रम println(5)और के बीच के अंतर को इंगित कर रहा हूं ()। या आप अंतिम वाक्य का मतलब?
जूलब

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

मैं स्पष्ट रूप से आपके उदाहरण को नहीं समझता हूँ
नाम

5
मैं कहता हूं कि यह गलत है क्योंकि किसी चीज का साइड इफेक्ट होना पूरी तरह से संभव है और ऐसा न हो कि इसे दोहराने से प्रभाव न बदले। एक परिवर्तनशील चर के लिए उदाहरण के लिए असाइनमेंट; आप कैसे भेद कर सकते हैं x = 1और x = 1; x = 1; x = 1?
एलेक्सी रोमानोव

5

निम्नलिखित सादृश्य पर विचार करें

var out: String = ""
def myprintln(s: String) = {
  out += s // this non-local mutation makes me impure
  ()
}

यहां myprintlnअशुद्ध है क्योंकि रिटर्निंग वैल्यू के ()साथ-साथ यह गैर-स्थानीय चर outको भी साइड-इफेक्ट के रूप में बदल देता है। अब outस्ट्रीम वेनिला printlnम्यूट होने की कल्पना करें ।


1
धन्यवाद, जवाब देने के लिए, यह स्पष्ट है कि आपका कार्य अशुद्ध है, हालांकि, क्यों प्रिंटल (), जैसा कि स्कला में परिभाषित किया गया है, शुद्ध नहीं है
नाम

1
@aName क्योंकि वापसी मूल्य के अलावा ()यह गैर-स्थानीय स्थिति को भी बदल देता है System.out
मारियो गैलेक्स

मुझे लगता है कि इस उत्तर से गायब महत्वपूर्ण तथ्य यह है कि Println इनपुट में एक नई लाइन वर्ण जोड़ता है।
फेडरिको एस

4

साइड इफेक्ट कंप्यूटर की स्थिति में है। हर बार जब आप println()टर्मिनल को दिए गए मूल्य को प्रदर्शित करने के लिए स्मृति परिवर्तन की स्थिति कहते हैं । या अधिक आम तौर पर, मानक आउटपुट स्ट्रीम की स्थिति बदल जाती है।


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

2
इस तरह, कोई भी कार्य, ऑपरेशन .... अशुद्ध हो जाएगा, क्योंकि यह बदल जाता है, स्मृति सीपीयू की स्थिति .....,
नाम

2

इस प्रश्न के अच्छे उत्तर पहले से ही दिए गए थे, लेकिन मुझे अपने दो सेंट जोड़ने चाहिए।

यदि आप printlnअनिवार्य रूप से फ़ंक्शन के अंदर देखेंगे , तो यह उसी तरह है java.lang.System.out.println()- इसलिए जब आप हड के printlnतहत स्काला के मानक पुस्तकालय विधि को लागू करते हैं तो यह ऑब्जेक्ट उदाहरण printlnपर विधि को आमंत्रित करता है PrintStreamजिसे कक्षा outमें क्षेत्र के रूप में घोषित किया जाता है System(या वस्तु outVarमें अधिक सटीक रूप से Console), जो इसे आंतरिक स्थिति बदलता है । यह एक और एक स्पष्टीकरण के रूप में माना जा सकता है कि printlnअशुद्ध कार्य क्यों है।

उम्मीद है की यह मदद करेगा!


1

इसका संदर्भात्मक पारदर्शिता की अवधारणा के साथ करना है । यदि आप प्रोग्राम को बदले बिना उसका मूल्यांकन परिणाम के साथ कर सकते हैं, तो यह अभिव्यक्ति संदर्भित रूप से पारदर्शी है ।

जब कोई अभिव्यक्ति संदर्भित रूप से पारदर्शी नहीं होती है तो हम कहते हैं कि इसके दुष्प्रभाव हैं

f(println("effect"), println("effect"))
// isn't really equivalent to!
val x = println("effect")
f(x, x)

जबकि

import cats.effect.IO

def printlnIO(line: String): IO[Unit] = IO(println(line))

f(printlnIO("effect"), printlnIO("effect"))
// is equivalent to
val x = printlnIO("effect")
f(x, x)

आप यहां अधिक विस्तृत विवरण पा सकते हैं: https://typelevel.org/blog/2017/05/02/io-monad-for-c.html


मैं यह नहीं देखता कि f (x, x) f (println ("प्रभाव"), println ("प्रभाव") से अलग क्यों है !!
aName

f(println("effect"), println("effect"))सांत्वना "प्रभाव" में दो बार प्रिंट करने जा रहा है जबकि val x = println("effect");f(x,x)एक बार प्रिंट करने जा रहा है।
दीदाक मोनटेरो

समारोह की परिभाषा क्या है f
नाम
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.