इंटरनेट में इस सवाल के लिए पहले से ही बहुत सारे शानदार जवाब हैं। मैं कई स्पष्टीकरणों और उदाहरणों का संकलन लिखूंगा, जो मैंने विषय के बारे में एकत्र किए हैं, बस अगर कोई व्यक्ति इसे उपयोगी समझ सकता है
परिचय
कॉल-बाय-वैल्यू (CBV)
आमतौर पर, फ़ंक्शन के पैरामीटर कॉल-बाय-वैल्यू पैरामीटर हैं; अर्थात्, फंक्शन का मूल्यांकन होने से पहले, उनके मान का निर्धारण करने के लिए मापदंडों का बाएं से दाएं मूल्यांकन किया जाता है
def first(a: Int, b: Int): Int = a
first(3 + 4, 5 + 6) // will be reduced to first(7, 5 + 6), then first(7, 11), and then 7
कॉल-बाय-नेम (CBN)
लेकिन क्या होगा अगर हमें एक फ़ंक्शन लिखने की ज़रूरत है जो एक पैरामीटर के रूप में स्वीकार करता है एक अभिव्यक्ति जिसे हम मूल्यांकन नहीं करते हैं जब तक कि इसे हमारे फ़ंक्शन के भीतर नहीं कहा जाता है? इस परिस्थिति के लिए, स्काला कॉल-बाय-नेम पैरामीटर प्रदान करता है। मतलब पैरामीटर को फंक्शन में पास किया जाता है जैसा कि है, और प्रतिस्थापन के बाद इसका मूल्यांकन होता है
def first1(a: Int, b: => Int): Int = a
first1(3 + 4, 5 + 6) // will be reduced to (3 + 4) and then to 7
कॉल-बाय-नेम तंत्र कॉल के लिए एक कोड ब्लॉक पास करता है और हर बार कॉल पैरामीटर तक पहुंचने के बाद, कोड ब्लॉक निष्पादित होता है और मूल्य की गणना की जाती है। निम्नलिखित उदाहरण में, विलंबित संदेश प्रदर्शित करता है कि विधि दर्ज की गई है। इसके बाद, विलंबित एक संदेश को इसके मूल्य के साथ प्रिंट करता है। अंत में, विलंबित रिटर्न 't':
object Demo {
def main(args: Array[String]) {
delayed(time());
}
def time() = {
println("Getting time in nano seconds")
System.nanoTime
}
def delayed( t: => Long ) = {
println("In delayed method")
println("Param: " + t)
}
}
विलंबित विधि
में नैनो सेकंड में समय प्राप्त करना
परम: 2027245119786400
प्रत्येक मामले के लिए PROS और CONS
CBN:
+ अधिक बार टर्मिनेट करता है * टर्मिनेशन के ऊपर नीचे की जाँच करें * + क्या फायदा है कि एक फ़ंक्शन तर्क का मूल्यांकन नहीं किया जाता है यदि फ़ंक्शन बॉडी के मूल्यांकन में संबंधित पैरामीटर अप्रयुक्त है-यह धीमा है, यह अधिक कक्षाएं बनाता है (मतलब प्रोग्राम लेता है) अब लोड करने के लिए) और यह अधिक मेमोरी खपत करता है।
CBV:
+ यह CBN की तुलना में अक्सर अधिक कुशल होता है, क्योंकि यह बार-बार होने वाले तर्कों के दोहराव से बच जाता है, जिसे नाम से पुकारा जाता है। यह प्रत्येक फ़ंक्शन तर्क का केवल एक बार मूल्यांकन करता है + यह अनिवार्य प्रभावों और दुष्प्रभावों के साथ बहुत अच्छा खेलता है, क्योंकि आप बहुत बेहतर जानते हैं कि जब अभिव्यक्तियों का मूल्यांकन किया जाएगा। -इसके मापदंडों के मूल्यांकन के दौरान एक लूप हो सकता है * समाप्ति से नीचे की जाँच करें *
क्या होगा अगर समाप्ति की गारंटी नहीं है?
-अगर किसी अभिव्यक्ति का CBV मूल्यांकन ई समाप्त होता है, तो CBN का मूल्यांकन भी समाप्त हो जाता है-अन्य दिशा सत्य नहीं है
गैर-समाप्ति उदाहरण
def first(x:Int, y:Int)=x
पहले अभिव्यक्ति पर विचार करें (1, लूप)
CBN: पहला (1, लूप) → 1 CBV: पहला (1, लूप) → इस अभिव्यक्ति के तर्कों को कम करता है। चूंकि एक लूप है, इसलिए यह तर्क को कम कर देता है। यह समाप्त नहीं होता है
प्रत्येक मामले में विभिन्न स्रोतों
आइए एक विधि परीक्षण को परिभाषित करें जो होगा
Def test(x:Int, y:Int) = x * x //for call-by-value
Def test(x: => Int, y: => Int) = x * x //for call-by-name
Case1 परीक्षण (2,3)
test(2,3) → 2*2 → 4
चूंकि हम पहले से ही मूल्यांकन किए गए तर्कों के साथ शुरू करते हैं, इसलिए यह कॉल-बाय-वैल्यू और कॉल-बाय-नाम के चरणों की समान राशि होगी
Case2 परीक्षण (3 + 4,8)
call-by-value: test(3+4,8) → test(7,8) → 7 * 7 → 49
call-by-name: (3+4)*(3+4) → 7 * (3+4) → 7 * 7 → 49
इस मामले में कॉल-बाय-वैल्यू कम चरण करता है
Case3 परीक्षण (7, 2 * 4)
call-by-value: test(7, 2*4) → test(7,8) → 7 * 7 → 49
call-by-name: (7)*(7) → 49
हम दूसरे तर्क की अनावश्यक गणना से बचते हैं
Case4 परीक्षण (3 + 4, 2 * 4)
call-by-value: test(7, 2*4) → test(7,8) → 7 * 7 → 49
call-by-name: (3+4)*(3+4) → 7*(3+4) → 7*7 → 49
अलग दृष्टिकोण
सबसे पहले, मान लें कि हमारे पास साइड-इफेक्ट वाला एक फ़ंक्शन है। यह फ़ंक्शन कुछ प्रिंट करता है और फिर एक Int देता है।
def something() = {
println("calling something")
1 // return value
}
अब हम दो फ़ंक्शन को परिभाषित करने जा रहे हैं जो Int तर्कों को स्वीकार करते हैं जो वास्तव में एक ही हैं सिवाय इसके कि कोई कॉल-बाय-वैल्यू स्टाइल (x: Int) में तर्क लेता है और दूसरा कॉल-बाय-नेम स्टाइल (x: => इंट)।
def callByValue(x: Int) = {
println("x1=" + x)
println("x2=" + x)
}
def callByName(x: => Int) = {
println("x1=" + x)
println("x2=" + x)
}
अब क्या होता है जब हम उन्हें अपने पक्ष प्रभाव वाले फ़ंक्शन के साथ कहते हैं?
scala> callByValue(something())
calling something
x1=1
x2=1
scala> callByName(something())
calling something
x1=1
calling something
x2=1
तो आप देख सकते हैं कि कॉल-बाय-वैल्यू संस्करण में, पास-इन फ़ंक्शन कॉल (कुछ ()) का साइड-इफेक्ट एक बार हुआ है। हालांकि, कॉल-बाय-नेम संस्करण में, साइड-इफेक्ट दो बार हुआ।
ऐसा इसलिए है क्योंकि कॉल-बाय-वैल्यू फ़ंक्शन फ़ंक्शन को कॉल करने से पहले पारित-किए गए अभिव्यक्ति के मूल्य की गणना करता है, इस प्रकार हर बार उसी मूल्य को एक्सेस किया जाता है। हालाँकि, कॉल-बाय-नेम फ़ंक्शंस हर बार इसे एक्सेस किए जाने के बाद से पास किए गए एक्सप्रेशन के मूल्य को फिर से जोड़ते हैं।
जहां इसका उपयोग CALL-BY-NAME के करीब है
प्रेषक: https://stackoverflow.com/a/19036068/1773841
सरल प्रदर्शन उदाहरण: लॉगिंग।
आइए इस तरह के एक इंटरफेस की कल्पना करें:
trait Logger {
def info(msg: => String)
def warn(msg: => String)
def error(msg: => String)
}
और फिर इस तरह इस्तेमाल किया:
logger.info("Time spent on X: " + computeTimeSpent)
यदि सूचना विधि कुछ भी नहीं करती है (क्योंकि, कहते हैं, लॉगिंग स्तर उस से अधिक के लिए कॉन्फ़िगर किया गया था), तो समय को बचाने के लिए computeTimeSpent को कभी भी कॉल नहीं किया जाता है। यह लॉगर के साथ बहुत कुछ होता है, जहां अक्सर स्ट्रिंग हेरफेर देखता है जो लॉग किए जा रहे कार्यों के सापेक्ष महंगा हो सकता है।
सही उदाहरण: तर्क ऑपरेटर।
आपने शायद इस तरह कोड देखा है:
if (ref != null && ref.isSomething)
कल्पना कीजिए कि आप इस तरह से && विधि की घोषणा करेंगे:
trait Boolean {
def &&(other: Boolean): Boolean
}
फिर, जब भी रेफ अशक्त होता है, तो आपको एक त्रुटि मिलेगी क्योंकि && को पास किए जाने से पहले आइसोलेटिंग को एक अशक्तता पर बुलाया जाएगा। इस कारण से, वास्तविक घोषणा है:
trait Boolean {
def &&(other: => Boolean): Boolean =
if (this) this else other
}
=> Int
से एक अलग प्रकार हैInt
; यह "कोई तर्क है कि उत्पन्न होगा एक के समारोह हैInt
बनाम बस"Int
। एक बार प्रथम श्रेणी के कार्य करने के बाद आपको इसका वर्णन करने के लिए कॉल-बाय-नेम शब्दावली का आविष्कार करने की आवश्यकता नहीं है ।