मैंने अभी-अभी जाना है कि आलसी मूल्यांकन कैसे काम करता है और मैं सोच रहा था: वर्तमान में उत्पादित हर सॉफ्टवेयर में आलसी मूल्यांकन क्यों लागू नहीं होता है? अभी भी उत्सुक मूल्यांकन का उपयोग क्यों?
मैंने अभी-अभी जाना है कि आलसी मूल्यांकन कैसे काम करता है और मैं सोच रहा था: वर्तमान में उत्पादित हर सॉफ्टवेयर में आलसी मूल्यांकन क्यों लागू नहीं होता है? अभी भी उत्सुक मूल्यांकन का उपयोग क्यों?
जवाबों:
आलसी मूल्यांकन के लिए बुक-कीपिंग ओवरहेड की आवश्यकता होती है- आपको यह जानना होगा कि क्या इसका मूल्यांकन अभी तक किया गया है और ऐसी चीजें। उत्सुक मूल्यांकन हमेशा मूल्यांकन किया जाता है, इसलिए आपको पता नहीं है। यह समवर्ती संदर्भों में विशेष रूप से सच है।
दूसरी बात यह है कि यदि आप चाहें तो बाद में इसे किसी फंक्शन ऑब्जेक्ट में पैकेजिंग द्वारा आलसी मूल्यांकन में उत्सुक मूल्यांकन में परिवर्तित करना तुच्छ है।
तीसरे, आलसी मूल्यांकन से नियंत्रण का नुकसान होता है। अगर मैं किसी डिस्क से किसी फ़ाइल को पढ़ने का मूल्यांकन करता हूं तो क्या होगा? या समय मिल रहा है? यह स्वीकार्य नहीं है।
उत्सुक मूल्यांकन अधिक कुशल और अधिक नियंत्रणीय हो सकता है, और तुच्छ रूप से आलसी मूल्यांकन में परिवर्तित किया जा सकता है। आप आलसी मूल्यांकन क्यों चाहते हैं?
readFile
है वास्तव में मैं क्या जरूरत है। इसके अलावा, आलसी से उत्सुक मूल्यांकन में परिवर्तित करना बस तुच्छ है।
head [1 ..]
आपको उत्सुकता से मूल्यांकन की गई शुद्ध भाषा में 1
क्या देता है, क्योंकि हास्केल में यह देता है ?
मुख्य रूप से क्योंकि आलसी कोड और राज्य बुरी तरह से मिश्रण कर सकते हैं और कीड़े खोजने के लिए कुछ मुश्किल पैदा कर सकते हैं। यदि किसी आश्रित वस्तु की स्थिति में परिवर्तन होता है तो मूल्यांकन के समय आपकी आलसी वस्तु का मूल्य गलत हो सकता है। यह बेहतर है कि प्रोग्रामर स्पष्ट रूप से वस्तु को आलसी होने के लिए कोड दे जब वह जानता है कि स्थिति उपयुक्त है।
एक साइड नोट पर हास्केल हर चीज के लिए आलसी मूल्यांकन का उपयोग करता है। यह संभव है क्योंकि यह एक कार्यात्मक भाषा है और राज्य का उपयोग नहीं करता है (कुछ असाधारण परिस्थितियों को छोड़कर जहां वे स्पष्ट रूप से चिह्नित हैं)
set!
एक आलसी योजना दुभाषिया में उपयोग करने के बारे में थे । > :(
आलसी मूल्यांकन हमेशा बेहतर नहीं होता है।
आलसी मूल्यांकन के प्रदर्शन लाभ महान हो सकते हैं, लेकिन उत्सुक वातावरणों में सबसे अनावश्यक मूल्यांकन से बचना मुश्किल नहीं है- निश्चित रूप से आलसी इसे आसान और पूर्ण बनाता है, लेकिन कोड में एक बड़ी समस्या का शायद ही कभी अनावश्यक मूल्यांकन होता है।
आलसी मूल्यांकन के बारे में अच्छी बात यह है कि यह आपको स्पष्ट कोड लिखने देता है; अनंत प्राकृतिक नंबरों की सूची को फ़िल्टर करके और उस सूची के 10 वें तत्व को ले कर 10 वाँ प्रधान स्थान प्राप्त करना आगे बढ़ने का सबसे संक्षिप्त और स्पष्ट तरीका है: (स्यूडोकोड)
let numbers = [1,2...]
fun is_prime x = none (map (y-> x mod y == 0) [2..x-1])
let primes = filter is_prime numbers
let tenth_prime = first (take primes 10)
मेरा मानना है कि आलसीपन के बिना चीजों को इतनी बारीकी से व्यक्त करना काफी मुश्किल होगा।
लेकिन आलसीपन हर चीज का जवाब नहीं है। शुरुआत के लिए, आलसीपन को राज्य की उपस्थिति में पारदर्शी रूप से लागू नहीं किया जा सकता है, और मेरा मानना है कि राज्यवारता का स्वचालित रूप से पता नहीं लगाया जा सकता है (जब तक कि आप यह नहीं कह रहे हैं, हास्केल, जब राज्य काफी स्पष्ट है)। इसलिए, अधिकांश भाषाओं में, आलसीपन को मैन्युअल रूप से करने की आवश्यकता होती है, जो चीजों को कम स्पष्ट करती है और इस प्रकार आलसी के बड़े लाभों में से एक को हटा देती है।
इसके अलावा, आलसीपन में कमियां होती हैं, क्योंकि यह गैर-मूल्यांकित अभिव्यक्तियों को बनाए रखने का एक महत्वपूर्ण ओवरहेड है; वे भंडारण का उपयोग करते हैं और वे सरल मूल्यों की तुलना में काम करने के लिए धीमी हैं। यह पता लगाना असामान्य नहीं है कि आपको उत्सुक-इफ कोड में होना चाहिए क्योंकि आलसी संस्करण कुत्ते के लिए धीमा है- और कभी-कभी प्रदर्शन के बारे में तर्क करना मुश्किल होता है।
जैसा कि यह होता है, कोई सबसे अच्छी रणनीति नहीं है। आलसी महान है यदि आप अनंत डेटा संरचनाओं या अन्य रणनीतियों का लाभ उठाते हुए बेहतर कोड लिख सकते हैं जो आपको उपयोग करने की अनुमति देता है, लेकिन उत्सुकता को अनुकूलित करना आसान हो सकता है।
यहाँ पेशेवरों और उत्सुक और आलसी मूल्यांकन के विपक्ष की एक छोटी तुलना है:
उत्सुक मूल्यांकन:
जरूरत से ज्यादा सामान का मूल्यांकन करने वाले संभावित ओवरहेड।
अनछुए, तेजी से मूल्यांकन।
आलसी मूल्यांकन:
कोई अनावश्यक मूल्यांकन नहीं।
मूल्य के प्रत्येक उपयोग पर बहीखाता ओवरहेड।
इसलिए, यदि आपके पास कई भाव हैं जिनका कभी मूल्यांकन नहीं करना है, तो आलसी बेहतर है; फिर भी यदि आपके पास कभी कोई अभिव्यक्ति नहीं है जिसका मूल्यांकन करने की आवश्यकता नहीं है, तो आलसी शुद्ध उपरि है।
अब, वास्तविक विश्व सॉफ़्टवेयर पर एक नज़र डालते हैं: आपके द्वारा लिखे गए कितने कार्यों को उनके सभी तर्कों के मूल्यांकन की आवश्यकता नहीं है? विशेष रूप से आधुनिक छोटे कार्यों के साथ जो केवल एक ही कार्य करते हैं, इस श्रेणी में कार्यों का प्रतिशत बहुत कम है। इस प्रकार, आलसी मूल्यांकन केवल बहीखाता ओवरहेड को ज्यादातर समय पेश करेगा, वास्तव में कुछ भी बचाने का मौका दिए बिना।
नतीजतन, आलसी मूल्यांकन केवल औसत पर भुगतान नहीं करता है, उत्सुक मूल्यांकन आधुनिक कोड के लिए बेहतर फिट है।
जैसा कि @DeadMG ने कहा कि आलसी मूल्यांकन के लिए बुक-कीपिंग ओवरहेड की आवश्यकता होती है। यह उत्सुक मूल्यांकन के सापेक्ष महंगा हो सकता है। इस कथन पर विचार करें:
i = (243 * 414 + 6562 / 435.0 ) ^ 0.5 ** 3
यह गणना करने के लिए थोड़ी सी गणना करेगा। यदि मैं आलसी मूल्यांकन का उपयोग करता हूं, तो मुझे यह जांचने की आवश्यकता है कि क्या हर बार इसका उपयोग करने के बाद इसका मूल्यांकन किया गया है। यदि यह एक भारी उपयोग किए गए तंग लूप के अंदर है, तो ओवरहेड काफी बढ़ जाता है, लेकिन कोई लाभ नहीं है।
उत्सुक मूल्यांकन और एक सभ्य संकलक के साथ सूत्र की गणना संकलन समय पर की जाती है। अधिकांश ऑप्टिमाइज़र असाइनमेंट को किसी भी लूप से बाहर स्थानांतरित कर देंगे, यदि यह उपयुक्त है।
आलसी मूल्यांकन डेटा लोड करने के लिए सबसे उपयुक्त है, जिसे बार-बार एक्सेस किया जाएगा और पुनर्प्राप्त करने के लिए एक उच्च ओवरहेड होगा। इसलिए कोर कार्यक्षमता की तुलना में मामलों को किनारे करना अधिक उपयुक्त है।
सामान्य तौर पर यह उन चीजों का मूल्यांकन करने के लिए अच्छा अभ्यास है जो अक्सर जल्दी से जल्दी पहुंच जाते हैं। आलसी मूल्यांकन इस अभ्यास के साथ काम नहीं करता है। यदि आप हमेशा कुछ हासिल करेंगे, तो सभी आलसी मूल्यांकन ओवरहेड जोड़ देंगे। आलसी मूल्यांकन का उपयोग करने की लागत / लाभ कम हो जाता है क्योंकि जिस वस्तु तक पहुँचा जा सकता है, उसके एक्सेस होने की संभावना कम हो जाती है।
हमेशा आलसी मूल्यांकन का उपयोग करना भी प्रारंभिक अनुकूलन का अर्थ है। यह एक बुरा अभ्यास है जिसके परिणामस्वरूप अक्सर कोड होता है जो बहुत अधिक जटिल और महंगा होता है जो अन्यथा मामला हो सकता है। दुर्भाग्य से, समय से पहले अनुकूलन अक्सर कोड में परिणाम होता है जो सरल कोड की तुलना में धीमा प्रदर्शन करता है। जब तक आप अनुकूलन के प्रभाव को माप नहीं सकते, तब तक अपने कोड को अनुकूलित करना एक बुरा विचार है।
समय से पहले अनुकूलन से बचना अच्छा कोडिंग प्रथाओं के साथ संघर्ष नहीं करता है। यदि अच्छी प्रथाओं को लागू नहीं किया गया था, तो प्रारंभिक अनुकूलन में अच्छी कोडिंग प्रथाओं को लागू करना शामिल हो सकता है जैसे कि लूप से बाहर की गणना।
अगर हमें संभावित रूप से किसी मूल्य का निर्धारण करने के लिए पूरी तरह से अभिव्यक्ति का मूल्यांकन करना है तो आलसी मूल्यांकन एक नुकसान हो सकता है। कहो कि हमारे पास बूलियन मूल्यों की एक लंबी सूची है और हम यह पता लगाना चाहते हैं कि क्या ये सभी सत्य हैं:
[True, True, True, ... False]
ऐसा करने के लिए हमें सूची में मौजूद प्रत्येक तत्व को देखना होगा , चाहे वह कुछ भी हो, इसलिए मूल्यांकन में आलस्य को काटने की कोई संभावना नहीं है। हम यह निर्धारित करने के लिए एक तह का उपयोग कर सकते हैं कि सूची में सभी बूलियन मान सही हैं या नहीं। यदि हम एक तह सही का उपयोग करते हैं, जो आलसी मूल्यांकन का उपयोग करता है, तो हमें आलसी मूल्यांकन का कोई लाभ नहीं मिलता है क्योंकि हमें सूची में प्रत्येक तत्व को देखना होगा:
foldr (&&) True [True, True, True, ... False]
> 0.27 secs
इस मामले में एक गुना दायाँ हिस्सा सख्त गुना की तुलना में बहुत धीमा होगा, जो आलसी मूल्यांकन का उपयोग नहीं करता है:
foldl' (&&) True [True, True, True, ... False]
> 0.09 secs
इसका कारण है एक सख्त तह बायाँ पूंछ पुनरावृत्ति का उपयोग करता है, जिसका अर्थ है कि यह रिटर्न वैल्यू जमा करता है और निर्माण और मेमोरी की एक बड़ी श्रृंखला में स्टोर नहीं करता है। यह आलसी फोल्ड राइट की तुलना में बहुत तेज है क्योंकि दोनों फंक्शंस को वैसे भी पूरी लिस्ट को देखना होता है और फोल्ड राइट टेल रीसर्शन का उपयोग नहीं कर सकता है। तो, मुद्दा यह है, आपको उस कार्य का उपयोग करना चाहिए जो कार्य के लिए सबसे अच्छा है।