web-dev-qa-db-ja.com

Clojureキーワード引数

Common LISPでは、これを行うことができます:

(defun foo (bar &key baz quux)
  (list bar baz quux))

(foo 1 :quux 3 :baz 2) ; => (1 2 3)

Clojureにはキーワード引数がありません。 1つの選択肢はこれです:

(defn foo [bar {:keys [baz quux]}] 
  (list bar baz quux))

(foo 1 {:quux 3 :baz 2}) ; => (1 2 3)

ネストされた角かっこが多すぎて、常に入力して読み取る必要がありません。また、フラットリストではなく、引数として明示的なハッシュマップを渡す必要があります。

誰かが句読点爆弾を仕掛けたように見えないキーワード引数に相当する最も慣用的なClojureは何ですか?

52
Brian Carper

Clojureでキーワード引数をシミュレートする簡単な方法は、次のような残りのパラメーターでハッシュマップを使用することです。

> (defn kwtest [x & e] (:foo (apply hash-map e)))
#'user/kwtest
> (kwtest 12 :bar "ignored" :foo "returned")
"returned"

Rich Hickeyは clojure google groupからのこのメッセージ にマクロを提供しました。これはキーワードパラメータを提供します。 対応するスレッド には、キーワードパラメータがclojureでサポートされていない理由に関する情報が含まれています。基本的に、実行時のオーバーヘッドを回避するためです。リッチは私が上で示した方法を このメッセージ で説明します

38
rincewind

Clojure 1.2のこの回答を更新するために、 バインディングの破棄 のマップフォームによって提供されるデフォルトで完全なキーワード引数がサポートされるようになりました。

user> (defn foo [bar &{ :keys [baz quux] 
                        :or {baz "baz_default" quux "quux_default"}}]
         (list bar baz quux))
#'user/foo

user> (foo 1 :quux 3)
(1 "baz_default" 3)
98
Alex Stoddard

clojure.contrib.defに最近追加されたのはdefnkマクロで、キーワード引数を使用して関数を定義できます( ここ を参照)。

9
pmf