2010-11-26 2 views
11

필수 인수 x 및 선택적 인수 opt1 또는 키워드 인수 opt2를 사용하는 함수를 만들려고합니다.Clojure 키워드 및 선택적 인수 문제

는 지금은

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

해야하지만, 위의 서명은 x와 OPT1 모두가있는 경우

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

하지이

(foo 'x {:opt2 'opt2}) 
처럼 나 한테 키워드 인수 OPT2에 건네 줄 수가 있습니다

필수 인수 X와 opt1 또는 opt2, whe 중 하나를 사용하는 함수를 만들도록 도와주십시오. re 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? 또는 xy이 제공되지 않고 단일 :bar =>:baz 키워드 인수가 사용됩니까?

Clojure보다 함수 매개 변수를 구문 분석 할 때 훨씬 더 융통성이있는 Common Lisp조차도 적어도 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

당신이 어쨌든이 추가적으로 인수가 키워드 인자 또는없는 경우 확인해야 (나는 당신의 가정 또는 독점 또는) 그래서 당신은 이런 식으로 작업을 수행 할 수 있습니다

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

체크 인수를 그들이 키워드 경우 인수 또는 아닙니다. 하나의 선택적 매개 변수 만 있기 때문에 쉽습니다. 키워드 인수에 2가 필요한 경우 하나만 있는지 확인하십시오.