जीएचसी कार्यों को याद नहीं करता है।
हालाँकि, यह कोड में किसी भी दी गई अभिव्यक्ति की गणना प्रति बार एक बार में करता है कि उसके आस-पास का लंबो-एक्सप्रेशन दर्ज किया जाता है, या फिर कभी भी अगर वह शीर्ष स्तर पर है। यह निर्धारित करना कि लैम्बडा-एक्सप्रेशन कहाँ थोड़े पेचीदा हो सकते हैं, जब आप अपने उदाहरण में सिंथैटिक शुगर का उपयोग करते हैं, तो आइए, इनको समतुल्य अवरोही सिंटैक्स में परिवर्तित करें:
m1' = (!!) (filter odd [1..]) -- NB: See below!
m2' = \n -> (!!) (filter odd [1..]) n
(नोट: हास्केल 98 रिपोर्ट वास्तव (a %)
में इसके समान ही एक बाएं ऑपरेटर सेक्शन का वर्णन करती है \b -> (%) a b
, लेकिन GHC इसे बताता है (%) a
। ये तकनीकी रूप से अलग हैं क्योंकि वे इससे अलग हो सकते हैं seq
। मुझे लगता है कि मैंने इस बारे में GHC Trac टिकट जमा किया होगा।)
इसे देखते हुए, आप देख सकते हैं कि m1'
, अभिव्यक्ति filter odd [1..]
किसी भी लैम्ब्डा-एक्सप्रेशन में समाहित नहीं है, इसलिए यह केवल आपके प्रोग्राम के चलने के दौरान एक बार गणना की जाएगी , जबकि m2'
, filter odd [1..]
लैम्बडा-एक्सप्रेशन के दर्ज होने पर, हर बार, यानी के प्रत्येक आह्वान पर m2'
। जो आपके द्वारा देखे जा रहे समय के अंतर को स्पष्ट करता है।
वास्तव में, जीएचसी के कुछ संस्करण, कुछ अनुकूलन विकल्पों के साथ, उपरोक्त विवरण से अधिक मूल्य साझा करेंगे। यह कुछ स्थितियों में समस्याग्रस्त हो सकता है। उदाहरण के लिए, फ़ंक्शन पर विचार करें
f = \x -> let y = [1..30000000] in foldl' (+) 0 (y ++ [x])
जीएचसी ध्यान दे सकता है कि y
इस पर निर्भर नहीं करता है x
और फ़ंक्शन को फिर से लिखता है
f = let y = [1..30000000] in \x -> foldl' (+) 0 (y ++ [x])
इस मामले में, नया संस्करण बहुत कम कुशल है क्योंकि इसे मेमोरी से लगभग 1 जीबी पढ़ना होगा जहां y
संग्रहीत किया जाता है, जबकि मूल संस्करण निरंतर स्थान पर चलेगा और प्रोसेसर के कैश में फिट होगा। वास्तव में, जीएचसी 6.12.1 के तहत, फंक्शन f
लगभग दोगुनी तेजी से होता है जब अनुकूलन के बिना इसे संकलित किया जाता है -O2
।
seq
m1 10000000)। जब कोई अनुकूलन ध्वज निर्दिष्ट नहीं किया जाता है तो एक अंतर होता है। और आपके "f" के दोनों वेरिएंट्स में अनुकूलन की परवाह किए बिना 5356 बाइट्स की अधिकतम रेजिडेंसी है, जिस तरह से (जब कुल आवंटन कम होता है -O2 का उपयोग किया जाता है)।