2012-07-26 14 views
10

मैं इस फार्म का एक नक्शा है कहते हैं:बेहतर तरीका clojure में अगर-जाने

(def m {:a "A" :b "B"}) 

और मैं कुछ करने के लिए करता है, तो :a और :b दोनों शून्य नहीं हैं चाहता हूँ, मैं कर सकते हैं:

(if-let [a (:a m)] 
    (if-let [b (:b m)] 
     ... etc)) 

या

(if (and (:a m) (:b m)) 
    (let [{a :a b :b} m] 
     ... etc)) 

या यहाँ तक कि

+०१२३५१६४१०६
(if (every? m [:a :b]) 
    (let [{a :a b :b} m] 
     ... etc)) 

क्या यह प्राप्त करने के लिए कोई नीदर (यानी एक-पंक्ति) तरीका है? - Clojure की एक उपयोगी सुविधा map destructuring

user> (not-any? nil? [(m :a) (m :b)]) 
true 
user> (not-any? nil? [(m :a) (m :b) (m :d)]) 
false 
user> 

उत्तर

7

मैं एक मैक्रो व्यवहार आप चाहते बनाने के लिए यहां आवश्यक हो सकता है लगता है। मैं एक (अभी तक) कभी नहीं लिखा है, लेकिन निम्नलिखित प्रतिनिधित्व मेरे लिए चलता है कि यह काफी सरल हो सकता है:

(let [{:keys [a b]} m] 
    (when (every? identity [a b]) 
     (println (str "Processing " a " and " b)))) 

का उपयोग destructuring की :keys रूप से बाध्यकारी और every? चाबियों का एक वेक्टर destructure करने के एक एकल विनिर्देश सक्षम बनाता है और जांचें, और बाध्य स्थानीय निम्नलिखित कोड ब्लॉक में उपलब्ध हैं।

यह एक मैक्रो ऐसे (when-every? [keys coll] code-with-bindings)

के रूप में मैं मैक्रो कोड के साथ इस सवाल का जवाब अद्यतन कर सकते हैं अगर मैं समय के लिए बाहर काम करने के लिए कैसे करना है ले जा सकते हैं बनाने के लिए इस्तेमाल किया जा सकता।

1

not-any? इस के लिए एक अच्छा तरीका है। यह भी तथ्य है कि कारनामे and शॉर्ट सर्किट है, और पहले के नक्शे में किसी भी कुंजी दूसरा मानचित्र में नहीं मिला nil हो जाता है, एक falsy मूल्य:

(let [{a :a b :b} {:a 1 :b "blah"}] 
    (and a b (op a b))) 

ठीक है, तो यह दो एक की जगह लाइनों है .... यह nil और अन्य झूठी मानों के बीच अंतर नहीं करता है।

+2

सुनिश्चित नहीं हैं कि इस सवाल का जवाब ... – noahlz

+0

'(हर? कुछ? ...) बेहतर नहीं होगा? इस तरह आप दोहरी अस्वीकृति – kosii

+0

से बच सकते हैं? कई मामलों में मामूली समय में सुधार के लिए, जब कोई पाया जाता है तो जांचना बंद कर सकता है –

6

आप इस्तेमाल कर सकते हैं:

1

मुझे यकीन नहीं है कि क्या करना है यदि कुंजी में गैर-शून्य मान हैं या आप गैर-शून्य कुंजी या मान वापस लौटना चाहते हैं। तो, मैंने इसे वापस नॉन-नील कुंजियों के लिए हल किया है।

अंतिम समाधान के हिस्से के रूप में आप निम्न मध्यवर्ती चरण के रूप में निम्न का उपयोग करेंगे।

मैं अपने द्वारा उपयोग किए जाने वाले सभी चरणों को दिखा रहा हूं, पैडेंटिक नहीं, बल्कि एक पूर्ण उत्तर प्रदान करने के लिए। नामस्थान repl-test है। इसका मुख्य संबंध है।

repl-test.core=> (def m {:a "A" :b "B" :c nil}) 
#'repl-test.core/m 

repl-test.core=> (keys m) 
(:a :c :b) 

और फिर अंत में:

; Check key's value to determine what is filtered through. 
repl-test.core=> (filter #(if-not (nil? (%1 m)) (%1 m)) (keys m)) 
(:a :b) 
1

तरह से मैं एक बदसूरत एक लाइनर, जो काम करता है क्योंकि and अपने तर्क सूची में आखिरी बात रिटर्न अगर वे सब सच हो पाया द्वारा:

(if-let [[a b] (and (:a m) (:b m) [(:a m)(:b m)])] 
    (println "neither " a " nor " b " is falsey") 
    (println "at least one of " a " or " b " is falsey"))