53

在 Common Lisp 中,您可以这样做:

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

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

Clojure 没有关键字参数。一种替代方法是:

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

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

嵌套的括号太多,不得不一直打字和阅读。它还需要一个显式的哈希映射作为参数而不是平面列表传入。

什么是最惯用的 Clojure 等效关键字参数,看起来不像有人引爆了标点符号?

4

3 回答 3

101

为了更新 Clojure 1.2 的这个答案,现在有完整的关键字 arg 支持,其默认值由解构绑定的映射形式提供:

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)
于 2010-10-19T14:55:34.573 回答
39

在 clojure 中模拟关键字 args 的一种简单方法是在 rest 参数上使用 hash-map,如下所示:

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

Rich Hickey 在来自 clojure google 组的这条消息中提供了一个宏,它为您提供关键字参数。相应的线程包含有关为什么 clojure 不支持关键字参数的信息。基本上是为了避免运行时开销。Rich 解释了我在此消息中显示的方法

于 2009-04-04T23:19:19.207 回答
9

最近添加的clojure.contrib.defdefnk宏,它可以使用关键字参数定义函数(参见此处)。

于 2009-06-16T12:37:24.140 回答