2010-11-26 19 views
11

मैं एक ऐसा फ़ंक्शन बनाना चाहता हूं जो एक आवश्यक तर्क x लेता है, और या तो एक वैकल्पिक तर्क opt1 या एक कीवर्ड तर्क opt2।क्लोजर कीवर्ड और वैकल्पिक तर्क समस्या

अभी मैं

(defn foo x & [opt1 {:keys [opt2]}] 
    ... 

है लेकिन इसके बाद के संस्करण हस्ताक्षर केवल मुझे कीवर्ड तर्क opt2 में पारित जब दोनों एक्स और opt1 मौजूद है

(foo 'x 'opt1 {:opt2 'opt2}) 

नहीं की तरह इस

(foo 'x {:opt2 'opt2}) 
की सुविधा देता है

कृपया मुझे एक ऐसा फ़ंक्शन बनाने में सहायता करें जो आवश्यक तर्क X लेता है और या तो opt1 या opt2, whe पुनः opt2 एक कीवर्ड तर्क है।

धन्यवाद।

संपादित करें: मैं अन्य मैक्रोज़ के लिए भी ऐसा करना चाहता हूं। तो मुझे अभी भी defmacro का उपयोग करने की जरूरत है।

+0

'[clojure.contrib.def] से defnk' उपयोग करने पर विचार (http://richhickey.github.com/clojure-contrib/def-api.html) स्पष्ट destructuring के बजाय। – ffriend

+0

'defnk' को 1.2 के रूप में अधिक सुसंगत अंतर्निहित कार्यक्षमता के पक्ष में बहिष्कृत किया गया है। – kotarak

उत्तर

15

समस्या अस्पष्टता है। एक फ़ंक्शन (fn foo [x y & args]) पर विचार करें जो दो वैकल्पिक तर्क और फिर कीवर्ड तर्कों की संख्या लेता है। यदि आप इसे (foo :bar :baz) कहते हैं, तो आपका प्रोग्राम इसे कैसे संभालता है? x =>:bar, y =>:baz? या x और y प्रदान नहीं किया गया है, एक :bar =>:baz कीवर्ड तर्क के साथ?

यहां तक ​​कि सामान्य लिस्प में भी, जो कि फोरमिंग फ़ंक्शन पैरामीटर में क्लोजर की तुलना में अधिक लचीलापन है, कम से कम one popular book के अनुसार वैकल्पिक और कीवर्ड तर्कों को मिलाकर अनुशंसित नहीं किया जाता है।

आपकी सबसे अच्छी शर्त स्थिति तर्कों या आपके सभी पैरामीटर को कीवर्ड तर्कों में बदलने के लिए है। यदि आप कीवर्ड तर्क का उपयोग करते हैं, तो आप "वैकल्पिक" कीवर्ड पैरामीटर के लिए डिफ़ॉल्ट प्रदान करने के लिए हैश-मानचित्र विनाशकारी का उपयोग कर सकते हैं।

user> (defn foo [& {:keys [x y bar] 
        :or {x 1 y 2 bar 3}}] 
     (prn [x y bar])) 
#'user/foo 
user> (foo) 
[1 2 3] 
nil 
user> (foo :bar :baz) 
[1 2 :baz] 
nil 
2

आप अगर aditional तर्क कीवर्ड बहस या नहीं कर रहे हैं की जाँच करने के लिए है वैसे भी (मैं अपने मान या एक विशेष है या) ताकि आप इसे इस तरह कर सकते हैं:

(defn foo [& args] 
    (if (= (count args) 1) 
     (let [[opt1] args] (println opt1)) 
     (let [{:keys [opt2]} args] (println opt2)))) 

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

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