2010-01-14 11 views
5

मैं क्लोजर के साथ काम कर रहा हूं और जब मैंने पहले लिस्प्स के साथ डब किया है, तो मुझे घोंसला देने के लिए एक साफ रास्ता खोजने में परेशानी हो रही है। उदाहरण के लिए, निम्नलिखित समारोह पर विचार करें:अंदर कंड

(defn operate-on-list [xs] 
    (let [[unpack vector] (first xs)] 
    (cond 
     [(empty? xs) 'empty 
     unpack vector 
     :else (operate-on-list (rest xs))]))) 

यह एक सूची पर एक सुंदर मानक पुनरावर्ती आपरेशन है, लेकिन यह सूची में पहले तत्व पर कुछ काम करने के लिए इससे पहले कि यह सामग्री के साथ काम करता है की जरूरत है। मुद्दा यह है कि सूची खाली हो सकती है।

इस उदाहरण में, यह ((first xs) 1) को ((first xs) 0) और vector को unpack बदलने के लिए मुश्किल नहीं होगा, लेकिन यह जल्दी से बदसूरत हो जाता है अधिक काम (पहले XS) पर किया जाना चाहिए है।

क्या कोई कंड के माध्यम से चलो स्टेटमेंट का प्रभावी ढंग से उपयोग करने का कोई तरीका है?

धन्यवाद।

इस तरह की

-Nate

+0

हाय पाया जा सकता है - यह मेरे लिए स्पष्ट नहीं है कि तुम क्या यहाँ हासिल करने की कोशिश कर रहे हैं। आपको यह दिलचस्प http://www.assembla.com/spaces/clojure/tickets/200 और http://groups.google.com/group/clojure/browse_thread/thread/c1097ce07506fc39 मिल सकता है कृपया यह बताएं कि फ़ंक्शन क्या माना जाता है अपने प्रश्न में करने के लिए, और कुछ उदाहरण इनपुट और आउटपुट। वाक्यविन्यास एक वैध कंड कथन की तरह नहीं दिखता है क्योंकि कंडक्टर का शरीर वेक्टर में लपेटा जाता है। –

उत्तर

11

इस तरह के मामलों में, आप सबसे अच्छा कर रहे हैं if-let का उपयोग कर बंद:

(defn operate-on-list [xs] 
    (if-let [[unpack v] (first xs)] 
    (cond 
     unpack v 
     :else (operate-on-list (rest xs))))) 

इस कोड को चलता दिया सूची seq करने योग्य (सूची, वेक्टर, सरणी ...) वैक्टर के पहले तत्व के दूसरे तत्व को लौटाता है जिसका पहला तत्व सत्य है (जिसका अर्थ false यानहीं है 0)। nil वापस आ गया है यदि ऐसा कोई वेक्टर नहीं मिला है।

ध्यान दें कि vector एक अंतर्निहित कार्य है, इसलिए मैंने v को परिवर्तनीय नाम के रूप में चुना है, बस भविष्य में शरीर में कार्य का उपयोग करने की आवश्यकता होने पर। सबसे महत्वपूर्ण बात यह है कि आप अपने कंड वाक्यविन्यास में बहुत से ब्रैकेट का उपयोग कर रहे हैं; इस संस्करण में तय किया गया है।

अद्यतन: if-let के बारे में ध्यान देने योग्य दो अतिरिक्त बातें:

  1. रास्ता if-let काम करता है, अगर (first xs)nil (false ही होगा) होता है, बंधन destructuring कभी नहीं होता है, तो क्लोजर nil से [unpack v] पर बाध्य करने में सक्षम नहीं होने के बारे में शिकायत नहीं करेगा।

  2. इसके अलावा, if-let एक और को खंड (- हालांकि अगर आप किसी और खंड में हैं, तो आप जानते हैं कि वे false या nil जहां वैसे भी है जिसमें आप चर if-let बाइंडिंग वेक्टर में बाध्य करने का उल्लेख नहीं कर सकते हैं) स्वीकार करता है।

+2

यह भी देखें कि 'कब-लेट' जो आपके पास केवल एक शाखा होने पर अधिक मूर्खतापूर्ण है। – kotarak

+0

एक दूसरा नोट: ध्यान रखें कि 'if-let' यहां काम करता है, क्योंकि सूची में वैक्टर शामिल होना चाहिए। सामान्य रूप से '(जब-चलो [एक्स (पहले एस)] ...) '* * * के लिए एक विकल्प नहीं है (जब-चलो [एस (एसईसी एस)] (चलो [एफ (पहले एस)] ...)) '। – kotarak

2

क्रमबद्ध, एक letcond के दायरे के अंदर के साथ?

(defn operate-on-list [list] 
    (let [ el_first (first list) ] 
    (cond 
     (nil? el_first) (println "Finished") 
     :else (do 
     (let [ list_rest (rest list) ] 
       (println el_first) 
       (operate-on-list list_rest)))))) 

(operate-on-list '(1 2 3)) 

उत्पादन होता है:

1 
2 
3 
Finished 
+4

आपका 'डू' अनिवार्य है। –

+0

@ ब्रायन कार्पर: आप सही हैं; आप बस काम छोड़ सकते हैं। वह मेरे हिस्से (विशेष रूप से, प्रज्ञान) पर एक एलिसप हैंगओवर था। –

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