2012-11-05 11 views
7

का उपयोग कर बेहतर mapcat को समझने के लिए mapcat मैं एक उदाहरण ले लिया:मानचित्र और concat

user> (mapcat #(list % %) [1 2 3]) 
(1 1 2 2 3 3) 

और पुन: पेश करने के लिए क्या दस्तावेज़, का उपयोग कर उद्देश्य पर का वर्णन करने की कोशिश की, नक्शा और concat:

user> (doc mapcat) 
clojure.core/mapcat 
([f & colls]) 
    Returns the result of applying concat to the result of applying map 
    to f and colls. Thus function f should return a collection. 

ऐसा करने से:

user> (concat (map #(list % %) [1 2 3])) 
((1 1) (2 2) (3 3)) 

हालांकि आप देख सकते हैं कि यह काम नहीं करता है। मैं फिर भी इस तरह कम करने का उपयोग कर सकते है, लेकिन अगर यह सही है पता नहीं है:

user> (reduce #(concat %1 %2) (map #(vec (list % %)) [1 2 3])) 
(1 1 2 2 3 3) 

ऊपर काम करता है, लेकिन अगर इसे पुन: करने के लिए एक सही तरीका है, नक्शा और concat का उपयोग कर मैं नहीं जानता, क्या मैपकैट करता है।

असल में मैं मैपकैट हुड के तहत काम करता हूं।

क्या चल रहा है और मैं मैपकैट के स्रोत तक कैसे पहुंच सकता हूं? (मैं Emacs + nrepl उपयोग कर रहा हूँ)

+1

'लागू' का उपयोग करना शायद 'कम करें' से बेहतर है क्योंकि 'कम करें' तर्कों की प्रत्येक जोड़ी के लिए 'concat' करेगा।चूंकि 'कॉन्सट' आलसी है, जब मूल्य वास्तव में मजबूर हो जाते हैं तो आप एक _really_ गहरी कॉल स्टैक के साथ समाप्त हो सकते हैं, जिसके परिणामस्वरूप संभवतः एक स्टैक ओवरफ़्लो होता है। [यहां एक साधारण उदाहरण है।] (Https://www.refheap.com/paste/6409) – DaoWen

+2

बस एक टिप - 'कमी' के साथ आपके कार्यान्वयन में, किसी अज्ञात फ़ंक्शन में 'concat' को लपेटने की कोई आवश्यकता नहीं है। यह भी काम करेगा: '(संक्षिप्त (मानचित्र ...) को कम करें) 'और बेहतर है क्योंकि यह खाली इनपुट के मामले को बेहतर तरीके से संभालता है। – Alex

उत्तर

6
user=> (source mapcat) 
(defn mapcat 
    "Returns the result of applying concat to the result of applying map 
    to f and colls. Thus function f should return a collection." 
    {:added "1.0"} 
    [f & colls] 
    (apply concat (apply map f colls))) 
nil 
user=> 

कारण reduce भी काम करता है, क्योंकि यह प्रभावी रूप से है:

(concat '(1 1) '(2 2) '(3 3)) 
:,

(concat (concat '(1 1) '(2 2)) '(3 3)) 

apply, के रूप में स्रोत कोड में इस्तेमाल के लिए विस्तारित

concat के साथ आपके शुरुआती प्रयास में:

user=> (map #(list % %) [1 2 3]) 
    ((1 1) (2 2) (3 3)) 
    user=> (concat (list '(1 1) '(2 2) '(3 3))) 
    ((1 1) (2 2) (3 3)) 
    user=> (concat [1]) 
    (1) 

आप देख सकते हैं कि यदि आप एक ही तर्क के साथ concat पर कॉल करते हैं, तो यह तर्क देता है।

+1

(कॉन्सैट लागू करें (मानचित्र एफ कोल्स लागू करें)) अजीब लग रहा है। मैं इसे काम नहीं कर सकता। * (कॉन्सैट (मैप एफ कोल्स) लागू करें) * मेरे लिए काम करता है, लेकिन मुझे * लागू * के दोहरे उपयोग को समझ में नहीं आता है। उदाहरण के लिए * (कॉन्सैट लागू करें (मानचित्र लागू करें # (सूची%%) [1 2])) * काम नहीं करता है !? –

+0

लागू करें पैरामीटर की एक सूची चाहता है ताकि आपके उदाहरण के लिए केवल 1 पैरामीटर के साथ सही किला होगा (कॉन्सैट लागू करें (मानचित्र # (सूची%%) लागू करें [[1 2]])) – mikkom

2

concat एक विविध कार्य है Ie यह एन पैरामीटर ले सकता है जहां प्रत्येक पैरामीटर मान का अनुक्रम है i.e हस्ताक्षर (defn concat [& lst]]) बन जाता है। जबकि आपके उदाहरण में आप एक ही तर्क के साथ कॉन्सट को कॉल कर रहे हैं, यह मानते हुए कि कॉन्सट समेकित होने के लिए मूल्यों की एक सीईसी लेता है और यही कारण है कि आपको परिणाम क्यों मिलता है Ie सूची की एक ही सूची वापस लौटा दी जाती है।

(apply concat(apply map #(list % %) [1 2])) काम नहीं करेगा।

(apply map #(list % %) [[1 2]]) या (apply map #(list % %) [1 2] []) काम करेगा।

ऐसा इसलिए है क्योंकि लागू पैरामीटर मानों का अनुक्रम होने की अपेक्षा करता है और मानों के अनुक्रम में प्रत्येक आइटम लागू फ़ंक्शन के पैरामीटर के रूप में पारित किया जाएगा। लागू होने के आपके मामले में विफल होने पर कॉल (map #(list % %) 1 2) तक बढ़ जाएगा जो गलत है और त्रुटि संदेश यह भी दिखाता है कि यह लंबे समय तक अनुक्रम को परिवर्तित नहीं कर सकता है क्योंकि मानचित्र को अनुक्रमों के रूप में अनुक्रमों की आवश्यकता होती है।

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