2011-03-16 18 views
8

Fold (उर्फ reduce) को एक बहुत ही महत्वपूर्ण उच्च आदेश समारोह माना जाता है। Mapfold (see here) के संदर्भ में व्यक्त किया जा सकता है। लेकिन यह मेरे लिए व्यावहारिक से अधिक अकादमिक लगता है। योग, या उत्पाद, या अधिकतम संख्या प्राप्त करने के लिए एक सामान्य उपयोग हो सकता है, लेकिन ये फ़ंक्शन आमतौर पर किसी भी तर्क को स्वीकार करते हैं। तो (fold + 0 '(2 3 5)) लिखें जब (+ 2 3 5) ठीक काम करता है। मेरा सवाल यह है कि fold का उपयोग करने के लिए यह सबसे आसान या सबसे स्वाभाविक स्थिति है?कार्यात्मक भाषाओं में गुना/कम करने का व्यावहारिक उपयोग

+4

यदि '+' पहले से ही 2 से अधिक तर्क स्वीकार नहीं करता है, तो आप एक संस्करण को कैसे कार्यान्वित करेंगे? – Gabe

+2

'fold' 'मानचित्र' जैसे कई उच्च-स्तरीय उपयोगी कार्यों के लिए बिल्डिंग ब्लॉक है। आपका प्रोग्राम शायद कच्चे 'गुना 'की तुलना में उन कार्यों का उपयोग करने की अधिक संभावना है, लेकिन तथ्य यह है कि आप किसी भी प्रकार की फोल्ड के रूप में सूची का उपभोग करने वाली किसी भी कार्यक्षमता को बहुत अधिक कार्यान्वित कर सकते हैं, यह बहुत महत्वपूर्ण बनाता है। – dfan

उत्तर

12

fold की बात यह है कि इसे और अधिक सार है। ऐसा नहीं है कि आप उन चीजों को कर सकते हैं जिन्हें आप पहले नहीं कर सकते थे, यह है कि आप उन्हें अधिक आसानी से कर सकते हैं।

एक fold का उपयोग करके आप किसी भी समारोह है कि दो तत्वों पर परिभाषित किया गया है तत्वों का एक मनमाना संख्या को लागू करने के सामान्यीकरण कर सकते हैं। यह एक जीत है क्योंकि एक सूची के मुकाबले दो तर्क लागू करने वाले एक समारोह को लिखना, परीक्षण करना, बनाए रखना और संशोधित करना आमतौर पर अधिक आसान होता है। और लिखना, परीक्षण करना, बनाए रखना इत्यादि हमेशा समान है लेकिन समान कार्यक्षमता वाले दो के बजाय एक सरल कार्य है।

के बाद से fold (और उस बात के, map, filter, और दोस्तों के लिए) अच्छी तरह से परिभाषित किया है व्यवहार, यह अक्सर स्पष्ट प्रत्यावर्तन की तुलना में इन कार्यों का उपयोग कर कोड को समझने के लिए बहुत आसान है।

असल में, एक बार आपके पास एक संस्करण होने के बाद, आपको दूसरा "मुफ्त में" मिलता है। आखिरकार, आप एक ही परिणाम प्राप्त करने के लिए कम काम कर रहे हैं।

+0

आपने कोई उदाहरण नहीं दिया, लेकिन आपने मुझे कुछ अंतर्दृष्टि दी, धन्यवाद –

8

यहां कुछ सरल उदाहरण दिए गए हैं जहां reduce वास्तव में अच्छी तरह से काम करता है।

प्रत्येक उप-सूची की अधिकतम मानों का योग का पता लगाएं

Clojure:

user=> (def x '((1 2 3) (4 5) (0 9 1))) 
#'user/x 
user=> (reduce #(+ %1 (apply max %2)) 0 x) 
17 

रैकेट:

> (define x '((1 2 3) (4 5) (0 9 1))) 
> (foldl (lambda (a b) (+ b (apply max a))) 0 x) 
17 

एक सूची

से एक नक्शे के निर्माण

Clojure:

user=> (def y '(("dog" "bark") ("cat" "meow") ("pig" "oink"))) 
#'user/y 
user=> (def z (reduce #(assoc %1 (first %2) (second %2)) {} y)) 
#'user/z 
user=> (z "pig") 
"oink" 

एक और अधिक जटिल clojure reduce विशेषता उदाहरण के लिए, परियोजना यूलर समस्याओं 18 & 67 करने के लिए my solution की जाँच करें।

यह भी देखें: reduce vs. apply

4
  1. आपका उदाहरण (+ 2 3 4) ही काम करता है क्योंकि आप तर्क की संख्या पहले से पता है। फोल्ड सूचियों पर काम करते हैं जिनके आकार में भिन्नता हो सकती है।

  2. fold/reduce "सूची में एक सीडीआर-आईएनजी" पैटर्न का सामान्य संस्करण है। क्रमशः अनुक्रम के प्रत्येक तत्व को संसाधित करने के बारे में प्रत्येक एल्गोरिदम और उस से कुछ रिटर्न मान की गणना करने के बारे में व्यक्त किया जा सकता है। यह मूल रूप से foreach पाश का कार्यात्मक संस्करण है।

2

यहां एक उदाहरण है कि अभी तक कोई और उल्लेख नहीं किया गया है।

"गुना" की तरह एक छोटी सी, अच्छी तरह से परिभाषित इंटरफेस के साथ एक समारोह का उपयोग करके आप प्रोग्राम हैं जो इसका इस्तेमाल को तोड़ने के बिना है कि कार्यान्वयन बदल सकते हैं। उदाहरण के लिए, आप distributed version that runs on thousands of PCs बना सकते हैं, इसलिए इसका उपयोग करने वाला सॉर्टिंग एल्गोरिदम distributed sort बन जाएगा, और इसी तरह। आपके कार्यक्रम more robust, simpler, and faster बन गए हैं।

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

3

गुना का उपयोग कर कोड आमतौर पर पढ़ने के लिए अजीब है। यही कारण है कि लोग उपलब्ध होने पर — पर नक्शा, फ़िल्टर, मौजूद, योग, और इतने पर पसंद करते हैं। इन दिनों मैं मुख्य रूप से कंपाइलर्स और दुभाषियों को लिख रहा हूं; यहाँ कुछ तरीके है मैं गुना का उपयोग करें:

  • कंप्यूट एक समारोह, अभिव्यक्ति के लिए मुफ्त चर का सेट या लिखने
  • प्रकार की जाँच
  • संग्रह संचित के लिए, प्रतीक तालिका, जैसे करने के लिए एक समारोह का पैरामीटर जोड़ें परिभाषाओं के अनुक्रम से उत्पन्न सभी समझदार त्रुटि संदेशों में से
  • बूट समय पर एक स्मालटाक दुभाषिया के लिए सभी पूर्वनिर्धारित वर्गों जोड़े

क्या इन सभी का उपयोग करता है आम में है यह है कि अनुक्रम किसी प्रकार के सेट या शब्दकोश के बारे में जानकारी जमा कर रहा है। बेहद व्यावहारिक।

4

कॉमन लिस्प कार्यों में तर्क के किसी भी संख्या को स्वीकार नहीं करते।

एक निरंतर हर कॉमन लिस्प कार्यान्वयन CALL-ARGUMENTS-LIMIT में परिभाषित किया गया है, जो 50 या बड़ा होना चाहिए नहीं है।

इसका मतलब यह है कि ऐसे किसी भी portably लिखा समारोह कम से कम 50 तर्क को स्वीकार करना चाहिए। लेकिन यह हो सकता है सिर्फ 50

यह सीमा compilers संभवतः अनुकूलित बुला योजनाओं का उपयोग करने और सामान्य मामले में, जहां तर्कों की एक असीमित संख्या में भेजी जा सकती है प्रदान नहीं करने के लिए अनुमति देने के लिए मौजूद है।

इस प्रकार बहुत बड़ी सूची या वैक्टर पोर्टेबल कॉमन लिस्प कोड में (50 तत्वों से भी बड़ा) को संसाधित करने में, यह यात्रा निर्माणों का उपयोग करने, कम करने, नक्शा, और इसी तरह के लिए आवश्यक है। इस प्रकार (apply '+ large-list) का उपयोग न करना भी आवश्यक है लेकिन (reduce '+ large-list) का उपयोग करें।

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