2010-11-26 21 views
11

Gerekli bir argüman x ve isteğe bağlı argüman opt1 VEYA bir anahtar kelime argümanı opt2 olan bir işlev oluşturmak istiyorum.Clojure Anahtar Kelime ve İsteğe Bağlı Bağımsız Değişken Sorunu

Şu anda

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

var Ama yukarıdaki imza sadece x ve opt1 hem mevcut olduğunda

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

değil bu

(foo 'x {:opt2 'opt2}) 
gibi gibi beni anahtar kelime argüman opt2 geçmek sağlar

Lütfen gerekli argüman X'i veya opt1 veya opt2'yi seçen bir fonksiyon yaratmama yardım edin. re opt2 bir anahtar kelime argümanıdır.

Teşekkür ederiz.

DÜZENLEME: Diğer makrolar için de aynısını yapmak istiyorum. Bu yüzden hala defmacro kullanmam gerekiyor.

+0

'[clojure.contrib.def] 'den defnk' kullanılarak düşünün (http://richhickey.github.com/clojure-contrib/def-api.html) yerine açık Strüktür kırıcı arasında. – ffriend

+0

'defnk', 1.2'den daha tutarlı yerleşik işlevler lehine kullanımdan kaldırılmıştır. – kotarak

cevap

15

Sorun belirsizlik. İki isteğe bağlı argüman ve daha sonra herhangi bir sayıda anahtar kelime argümanını alan bir (fn foo [x y & args]) işlevini düşünün. Sonra (foo :bar :baz) gibi çağırırsanız, programınız bunu nasıl ele alır? x =>:bar, y =>:baz? Veya x ve y sağlanmadı, tek bir :bar =>:baz anahtar kelime değişkeni? 0 Hatta, bileğiştirme işlevi parametrelerinde Clojure'den daha fazla esnekliğe sahip olan Common Lisp'de bile, en az one popular book'a göre isteğe bağlı ve anahtar sözcük bağımsız değişkenlerini karıştırma önerilmez.

En iyi seçeneğiniz, tüm argümanlarınızı konum değişkenlerine veya tüm parametrelerinizi anahtar kelime bağımsız değişkenlerine dönüştürmektir. Anahtar kelime bağımsız değişkenleri kullanırsanız, "isteğe bağlı" anahtar kelime parametreleri için varsayılan değerler sağlamak üzere karma eşleme imha özelliğini kullanabilirsiniz.

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

yine AIP argümanlar anahtar kelime argümanlar ya da değil olup olmadığını kontrol etmek zorunda (Seninkini varsayalım veya özel bir ya da) bu yüzden böyle yapabilirsiniz:

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

onay argümanlar bunlar anahtar kelime olup olmadığını argümanlar ya da değil. Sadece bir tane isteğe bağlı parametreye sahip olduğunuzdan, kolay: anahtar kelime argümanları olarak sadece bir tane bulunup bulunmadığını kontrol edin.

İlgili konular