2013-01-02 27 views
7

मैं काफी Clojure के लिए नया हूँ, हालांकि मैं कार्यात्मक भाषाओं, मुख्य रूप से स्काला से परिचित हूँ।संचालन

मैं यह जानने की कोशिश कर रहा हूं कि क्लोजर में संग्रह पर काम करने के लिए बेवकूफ तरीका क्या है। मैं विशेष रूप से map जैसे कार्यों के व्यवहार से उलझन में हूं। इसके बजाय

List(1, 2, 3) map (2 *) == List(2, 4, 6) 
Set(1, 2, 3) map (2 *) == Set(2, 4, 6) 
Vector(1, 2, 3) map (2 *) == Vector(2, 4, 6) 

, Clojure में,:

स्काला में, एक बड़ी सावधानी बनाने ताकि map हमेशा मूल संग्रह के एक ही प्रकार का एक संग्रह वापस आ जाएगी में लिया जाता है, जब तक यह समझ में आता है के रूप में जहाँ तक मैं समझता हूँ, इस तरह के map या filter के रूप में सबसे संचालन आलसी हैं, तब भी जब उत्सुक डेटा संरचनाओं पर लागू। यह

(map #(* 2 %) [1 2 3]) 

एक आलसी-सूची के बजाय एक सदिश बनाने का अजीब परिणाम है।

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

कहें कि मैं ऊपर से परिणाम का उपयोग करता हूं और इसके अंत में जोड़ता हूं। अगर मैं सही ढंग से समझता हूं, तो परिणाम का मूल्यांकन तब तक नहीं किया जाता जब तक कि मैं इसे जोड़ने की कोशिश नहीं करता, फिर मूल्यांकन किया जाता है और मुझे वेक्टर की बजाय सूची मिलती है; तो मुझे अंत में जोड़ने के लिए इसे पार करना होगा। बेशक मैं इसे बाद में वेक्टर में बदल सकता हूं, लेकिन यह गन्दा हो जाता है और इसे अनदेखा किया जा सकता है।

अगर मैं सही ढंग से समझ, map बहुरूपी है और इसे लागू करने के लिए एक समस्या नहीं होगी, ताकि यह वैक्टर पर एक वेक्टर, सूची में एक सूची, नदियों पर एक धारा (आलसी अर्थ विज्ञान के साथ इस समय) और इतने पर रिटर्न है । मुझे लगता है कि मुझे क्लोजर और उसके मुहावरे के बुनियादी डिजाइन के बारे में कुछ याद आ रहा है।

कारण clojure डेटा संरचनाओं पर बुनियादी संचालन संरचना preverse नहीं है क्या है?

+0

मानचित्र के लिए स्रोत कोड देखें। मानचित्र संग्रह के प्रकार के बारे में परवाह नहीं करता है। आप मानचित्र के शीर्ष पर एक मैक्रो बना सकते हैं जो संग्रह के प्रकार को याद करता है, और संग्रह को अंत में उस प्रकार में परिवर्तित करता है। https://github.com/clojure/clojure/blob/master/src/clj/clojure/core/reducers.clj –

+1

https://github.com/ में clojure.algo.generic.functor/fmap पर एक नज़र डालें एक 'नक्शा' कार्यान्वयन के लिए clojure/algo.generic जो इनपुट प्रकार को संरक्षित करता है। – Alex

उत्तर

7

क्लोजर में कई फ़ंक्शन Seq अमूर्तता पर आधारित होते हैं। जब तक आपके संग्रह एक दृश्य (एक सिर और संभवतः एक पूंछ के साथ बातें), आप इसके साथ उपयोग कर सकते हैं के रूप में देखी जा सकती है - इस दृष्टिकोण का लाभ आप हर अलग संग्रह प्रकार के लिए एक समारोह लिखने के लिए की जरूरत नहीं है कि है सभी seq कार्यों। कार्य जो seqs और output seqs लेते हैं, वे अधिक संगत होते हैं और इस प्रकार उन कार्यों की तुलना में पुनः उपयोग करने योग्य होते हैं जो उनके उपयोग को किसी निश्चित संग्रह प्रकार तक सीमित करते हैं। जब seq पर अपने खुद के समारोह लिख तुम जैसे विशेष मामलों को संभालने के लिए की जरूरत नहीं है: यदि उपयोगकर्ता मुझे एक वेक्टर देता है, मैं एक सदिश वापस लौटाना होगा, आदि आपका समारोह बस के रूप में किसी अन्य रूप में seq पाइप लाइन के अंदर अच्छा में फिट होगा seq समारोह।

नक्शा एक आलसी सीईसी लौटने का कारण एक डिजाइन विकल्प है। क्लोजर आलस्य में इन कार्यात्मक निर्माणों में से कई के लिए डिफ़ॉल्ट है। यदि आप अन्य व्यवहार करना चाहते हैं, जैसे इंटरमीडिएट संग्रह के समानांतरता, रेड्यूसर लाइब्रेरी पर नज़र डालें: http://clojure.com/blog/2012/05/08/reducers-a-library-and-model-for-collection-processing.html

जहां तक ​​प्रदर्शन चलता है, मानचित्र को हमेशा संग्रह से फ़ंक्शन एन बार लागू करना होता है, पहले से अंतिम तत्व, इसलिए इसका प्रदर्शन हमेशा ओ (एन) या बदतर होगा। इस मामले में वेक्टर या सूची में कोई फर्क नहीं पड़ता। आलसी आपको वह लाभ प्रदान करेगी जब आप केवल सूची के पहले भाग का उपभोग करेंगे। यदि आपको मानचित्र के आउटपुट के अंत में कुछ जोड़ना होगा, तो वेक्टर वास्तव में अधिक कुशल है। आप इस मामले में mapv (क्लोजर 1.4 में जोड़े गए) का उपयोग कर सकते हैं: यह एक संग्रह में होता है और एक वेक्टर आउटपुट करेगा।मैं कहूंगा, केवल इन प्रदर्शन अनुकूलन के बारे में चिंता करें यदि आपके पास इसके लिए बहुत अच्छा कारण है। अधिकांश समय यह इसके लायक नहीं है।

seq अमूर्त के बारे में यहाँ और अधिक पढ़ें: http://clojure.org/sequences

एक अन्य वेक्टर लौटने उच्च आदेश समारोह है कि Clojure में जोड़ा गया 1.4 filterv है।

+1

मैं नहीं कहूंगा कि सूची बनाम वेक्टर कोई प्रदर्शन अंतर नहीं करता है - यह इस बात पर निर्भर करता है कि आप 'मानचित्र' के परिणामों का उपयोग कैसे करना चाहते हैं - उदा। '(एनएचटी (मानचित्र # (* 2%) वास्तव में लंबे समय तक वेक्टर) 10000)' – Alex

+0

@ एलेक्स, आप सही हैं, इस टिप्पणी को पोस्ट करने से पहले मैंने पहले ही अपना जवाब बदल दिया है –

+1

एक और बिंदु यह है कि अनुक्रम बनाना बहुत सस्ता है; वैक्टर बनाना, जबकि अभी भी सस्ता है, काफी महंगा है। 'नक्शा' विनम्रतापूर्वक सस्ती चीज कर रहा है, और अगर आपको इसे किसी कारण से चाहिए तो इसे बाद में वेक्टर में बदल दें। लेकिन यह भी: यदि आपके पास एक वेक्टर है जिसे आप मानचित्र बनाना चाहते हैं, तो आपको आमतौर पर केवल एक अनुक्रम की आवश्यकता होती है, न कि वेक्टर। – amalloy

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