2011-07-13 18 views
8

मैं बस एफ # शुरू कर रहा हूं इसलिए कृपया मूलभूत होने पर दयालु रहें।एफ # आलसी मूल्यांकन बनाम गैर-आलसी

मैंने पढ़ा है कि आलसी चिह्नित एक फ़ंक्शन का मूल्यांकन केवल एक बार किया जाता है और फिर कैश किया जाता है। उदाहरण के लिए:

let eagerFunc = (1 + 1) 
let theValue = eagerFunc 

उस आधार पर, सभी कार्यों आलसी किया जाना चाहिए:

let lazyFunc = lazy (1 + 1) 
let theValue = Lazy.force lazyFunc 

इस संस्करण जो वास्तव में हर बार यह कहा जाता है काम कर सके तुलना में? आप कब नहीं चाहेंगे यह "शुरुआती एफ #" पुस्तक में सामग्री से आ रहा है।

+0

एफ # का यह संस्करण क्या है? मेरे पास एक अनुक्रम है जो आलसी अभिनय कर रहा है, लेकिन उस तरह से अत्यधिक नहीं बनाया गया था। मैं इसे पूरा करने के लिए मजबूर करने की कोशिश कर रहा हूं। – octopusgrabbus

उत्तर

13

सबसे पहले, यह चीजें आप को परिभाषित किया है कि कोई भी नोट करने के लिए सहायक हो सकता है एक समारोह है - eagerFunc और theValue प्रकार का मान हैं int और lazyFunc प्रकार Lazy<int> के एक मूल्य है।

let lazyTwo = lazy (1 + 1) 

और

let eagerTwo = 1 + 1 

को देखते हुए अभिव्यक्ति 1 + 1नहीं एक बार कोई बात नहीं कितनी बार आप eagerTwo का उपयोग की तुलना में अधिक मूल्यांकन किया जाएगा। अंतर 1 + 1 का मूल्यांकन किया है कि हो जाएगा बिल्कुल एक बार जब को परिभाषित करनेeagerTwo, लेकिन सबसे एक बार जब lazyTwoइस्तेमाल किया है पर मूल्यांकन किया जाएगा (यह पहली बार मूल्यांकन किया जाएगा कि Value संपत्ति एक्सेस किया जाता है, और उसके बाद है कैश किया गया ताकि Value के आगे उपयोगों को फिर से गणना करने की आवश्यकता न हो)। यदि lazyTwo का Value कभी भी एक्सेस नहीं किया गया है, तो उसके शरीर 1 + 1कभी का मूल्यांकन नहीं किया जाएगा।

आमतौर पर, आपको F # जैसे सख्त भाषा में आलसी मूल्यों का उपयोग करने के लिए अधिक लाभ नहीं दिखाई देगा। Value संपत्ति तक पहुंचने के बाद से वे थोड़ी सी मात्रा में ओवरहेड जोड़ते हैं ताकि यह जांच करनी हो कि मूल्य की गणना पहले से ही की जा चुकी है या नहीं। यदि आपके पास let lazyValue = lazy someVeryExpensiveCalculationThatMightNotBeNeeded() जैसा कुछ है, तो वे आपको थोड़ी सी गणना बचा सकते हैं, क्योंकि महंगी गणना केवल तभी होगी जब मूल्य वास्तव में उपयोग किया जाता है। वे कुछ एल्गोरिदम भी समाप्त कर सकते हैं जो अन्यथा नहीं करेंगे, लेकिन यह F # में एक प्रमुख मुद्दा नहीं है। उदाहरण के लिए:

// throws an exception if x = 0.0 
let eagerDivision x = 
    let oneOverX = 1.0/x 
    if x = 0.0 then 
     printfn "Tried to divide by zero" // too late, this line is never reached 
    else 
     printfn "One over x is: %f" oneOverX 

// succeeds even if x = 0.0, since the quotient is lazily evaluated 
let lazyDivision x = 
    let oneOverX = lazy (1.0/x) 
    if x = 0.0 then 
     printfn "Tried to divide by zero" 
    else 
     printfn "One over x is: %f" oneOverX.Value 
+0

'()' का उपयोग नहीं करता है यह दर्शाता है कि यह एक कार्य है? किसी भी मामले में अच्छे अंक। आप सही हैं मेरे उदाहरण सुपर तुच्छ हैं। – Yuck

+0

@Yuck - कोष्ठक अलग-अलग संदर्भों में अलग-अलग चीजों का मतलब है। जब आप उन्हें '(1 + 1)' जैसे उपयोग करते हैं तो वे केवल समूह और प्राथमिकता को इंगित करने के लिए सेवा कर रहे हैं। यदि आपने 'eagerFunc() = ...' को परिभाषित किया है तो "कोष्ठक इंगित करते हैं कि 'eagerFunc' एक फ़ंक्शन है, लेकिन ध्यान दें कि यह आपके द्वारा लिखे गए कार्यों से अलग है। – kvb

6

समारोह फांसी दुष्प्रभाव और यह दुष्प्रभाव हर बार समारोह में कहा जाता है को देखने के लिए महत्वपूर्ण है (कहते हैं कि यह लपेटता एक आई/ओ समारोह) आप इसे आलसी होने के लिए नहीं करना चाहते।

वहाँ भी काम करता है कि इतने तुच्छ है कि उन्हें हर बार क्रियान्वित value--

5

let eagerFunc = (1 + 1) कैशिंग की तुलना में तेजी है एक बाध्यकारी हैं, और केवल एक बार निष्पादित करेंगे है। let eagerFunc() = (1 + 1) एक कार्य है जो unit (कुछ भी नहीं) स्वीकार कर रहा है और int लौटा रहा है। यह हर बार इसे निष्पादित करेगा। एक अर्थ में, प्रत्येक कार्य आलसी है, यानी, इसे बुलाए जाने पर ही निष्पादित होता है। हालांकि, lazy कीवर्ड (और System.Lazy, जो यह लौटाता है) इसे एक बार में दी गई अभिव्यक्ति/फ़ंक्शन निष्पादित करेगा। Value संपत्ति के बाद के कॉल कैश किए गए परिणाम लौटाएंगे। यह तब उपयोगी होता है जब मूल्य की गणना महंगा होती है।

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

संबंधित मुद्दे