Clojure关键字和可选参数问题

unj*_*nj2 11 clojure optional-parameters argument-passing

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

现在我有

(defn foo x & [opt1 {:keys [opt2]}]
  ...
Run Code Online (Sandbox Code Playgroud)

但是当x和opt1都存在时,上面的签名只允许我传入关键字参数opt2

(foo 'x 'opt1 {:opt2 'opt2})
Run Code Online (Sandbox Code Playgroud)

不喜欢这个

(foo 'x {:opt2 'opt2})
Run Code Online (Sandbox Code Playgroud)

请帮我创建一个带有必需参数X和opt1或opt2的函数,其中opt2是关键字参数.

谢谢.

编辑:我也想对其他宏做同样的事情.所以我仍然需要使用defmacro.

Bri*_*per 15

问题是含糊不清.考虑一个函数(fn foo [x y & args]),它接受两个可选参数,然后是任意数量的关键字参数.如果你那么称之为(foo :bar :baz),你的程序如何处理它? x=> :bar,y=> :baz?或xy不提供,具有单:bar=> :baz关键字参数?

根据至少一本流行的书,即使在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
Run Code Online (Sandbox Code Playgroud)