2008-11-22 13 views
5

मैं कार्यात्मक प्रोग्रामिंग सीख रहा हूं, और एक कार्यात्मक शैली में कुछ समस्याओं को हल करने की कोशिश की है। कार्यों में मेरी समस्या को विभाजित करते समय, मैंने अनुभव किया था, ऐसा लगता था कि मेरे पास दो विकल्प थे: समान पैरामीटर सूचियों के साथ कई अलग-अलग कार्यों का उपयोग करें, या नेस्टेड फ़ंक्शंस का उपयोग करना, जो बंद होने के रूप में, केवल मूल कार्य में बाइंडिंग का संदर्भ ले सकते हैं।नेस्टेड फ़ंक्शंस: साइड इफेक्ट्स का अयोग्य उपयोग?

हालांकि मैं दूसरे दृष्टिकोण के साथ जा रहा था, क्योंकि यह फ़ंक्शन कॉल को छोटा करता था और ऐसा लगता है कि मेरे पढ़ने से बेहतर महसूस होता है, ऐसा लगता है कि मैं कार्यात्मक प्रोग्रामिंग के मुख्य बिंदुओं में से एक को याद कर सकता हूं, उसमें यह "दुष्प्रभाव" लगता है? अब दिया गया है, इन घोंसले वाले कार्यों बाहरी बाइंडिंग को संशोधित नहीं कर सकते हैं, क्योंकि जिस भाषा का मैं उपयोग कर रहा था, उसे रोकता है, लेकिन यदि आप प्रत्येक आंतरिक कार्य को देखते हैं, तो आप यह नहीं कह सकते कि "एक ही पैरामीटर दिए गए हैं, यह फ़ंक्शन एक ही परिणाम देगा" क्योंकि वे माता-पिता के दायरे से चर का उपयोग करते हैं ... क्या मैं सही हूँ?

आगे बढ़ने का वांछनीय तरीका क्या है?

धन्यवाद!

उत्तर

2

घोंसले कार्य कई कार्यों में श्रम को विभाजित करने का एक शानदार तरीका है। यह वास्तव में "दुष्प्रभाव" नहीं है; अगर यह मदद करता है, तो कब्जे वाले चर के रूप में कब्जे वाले चर के बारे में सोचें।

एक उदाहरण जहां नेस्टेड फ़ंक्शंस उपयोगी हैं, लूप को प्रतिस्थापित करना है। नेस्टेड फ़ंक्शन के पैरामीटर प्रेरण चर के रूप में कार्य कर सकते हैं जो मान जमा करते हैं। एक साधारण उदाहरण:

let factorial n = 
    let rec facHelper p n = 
     if n = 1 then p else facHelper (p*n) (n-1) 
    in 
    facHelper 1 n 

इस मामले में, यह वास्तव में भावना विश्व स्तर पर facHelper की तरह एक समारोह की घोषणा करने, नहीं होगा, क्योंकि उपयोगकर्ताओं p पैरामीटर के बारे में चिंता करने की ज़रूरत नहीं होना चाहिए।

हालांकि, ध्यान रखें कि नेस्टेड फ़ंक्शंस को अलग-अलग परीक्षण करना मुश्किल हो सकता है, क्योंकि उन्हें अपने माता-पिता के बाहर संदर्भित नहीं किया जा सकता है।

putLines :: [String] -> IO() 
putLines lines = putStr string 
    where string = concat lines 

string एक स्थानीय रूप से निरंतर नामित बाध्य है:

+0

facHelper वास्तव में किसी बाहरी मूल्य का संदर्भ नहीं देता है - यह अभी भी पूरी तरह कार्यात्मक है। –

3

कार्यात्मक प्रोग्रामिंग सभी या कुछ भी नहीं है। यदि कार्यों को घोंसले करना अधिक समझ में आता है, तो मैं उस दृष्टिकोण के साथ जाऊंगा। हालांकि, यदि आप वास्तव में आंतरिक कार्यों को पूरी तरह से कार्यात्मक बनाना चाहते हैं, तो स्पष्ट रूप से उन सभी आवश्यक मानकों को पारित करें।

यहाँ योजना में एक छोटे से उदाहरण है:

(define (foo a) 
    (define (bar b) 
    (+ a b))  ; getting a from outer scope, not purely functional 
    (bar 3)) 

(define (foo a) 
    (define (bar a b) 
    (+ a b))  ; getting a from function parameters, purely functional 
    (bar a 3)) 


(define (bar a b) ; since this is purely functional, we can remove it from its 
    (+ a b))  ; environment and it still works 

(define (foo a) 
    (bar a 3)) 

व्यक्तिगत रूप से, मैं पहली बार दृष्टिकोण के साथ जाना चाहते हैं, लेकिन या तो समान रूप से अच्छी तरह से काम करेगा।

1

निम्नलिखित (काल्पनिक) हास्केल टुकड़ा पर विचार करें। लेकिन क्या यह एक ऐसा कार्य नहीं है जो से अधिक न हो जो तर्कसंगत रूप से अंतर्निहित है? (हास्केल में, स्थिरांक और नलिका कार्य वास्तव में अलग-अलग हैं!) क्या आप उपर्युक्त कोड "दुष्प्रभाव" या गैर-कार्यात्मक इस पर विचार करेंगे?

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