Clojure关键字和可选参数问题

Clojure关键字和可选参数问题,clojure,argument-passing,optional-parameters,Clojure,Argument Passing,Optional Parameters,我想创建一个函数,该函数接受一个必需的参数x,以及一个可选参数opt1或一个关键字参数opt2 现在我有 (defn foo x & [opt1 {:keys [opt2]}] ... 但是上面的签名只允许我在x和opt1同时出现时传入关键字参数opt2,就像 (foo 'x 'opt1 {:opt2 'opt2}) 不是这样的 (foo 'x {:opt2 'opt2}) 请帮助我创建一个函数,该函数接受一个必需的参数X和opt1或opt2,其中opt2是一个关键字参数 多谢

我想创建一个函数,该函数接受一个必需的参数x,以及一个可选参数opt1或一个关键字参数opt2

现在我有

(defn foo x & [opt1 {:keys [opt2]}]
  ...
但是上面的签名只允许我在x和opt1同时出现时传入关键字参数opt2,就像

(foo 'x 'opt1 {:opt2 'opt2})
不是这样的

(foo 'x {:opt2 'opt2})
请帮助我创建一个函数,该函数接受一个必需的参数X和opt1或opt2,其中opt2是一个关键字参数

多谢各位


编辑:我也想对其他宏执行同样的操作。因此,我仍然需要使用defmacro。

您必须检查传统参数是否为关键字参数(我假设您的or为异或),这样您就可以这样做:

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

检查参数是否为关键字参数。因为您只有一个可选参数,所以很容易:检查是否只有一个,因为关键字参数需要两个。

问题在于模糊性。考虑一个函数<代码>(fnfo[xy&ARgs]),它有两个可选参数和任意数量的关键字参数。如果您然后像
(foo:bar:baz)
那样调用它,那么您的程序如何处理它<代码>x=>
:条形图
y
=>
:baz
?或者未提供带有单个
:bar
=>
:baz
关键字参数的
x
y

即使在Common Lisp中(可以说它在解析函数参数方面比Clojure更具灵活性),也不建议混合使用可选参数和关键字参数,至少有一种说法是这样的

最好将所有参数更改为位置参数,或将所有参数更改为关键字参数。如果使用关键字参数,则可以使用哈希映射分解来为“可选”关键字参数提供默认值

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

考虑使用<代码> DEFNK<代码>而不是显式的破坏。<代码> DEFNK被禁止支持更一致的内置功能,如1.2。