如何将可选关键字参数与&rest内容混合使用?

Ray*_*yne 7 macros clojure destructuring

我有一个带有身体的宏:

(defmacro blah [& body] (dostuffwithbody))
Run Code Online (Sandbox Code Playgroud)

但是我也想为它添加一个可选的关键字参数,所以在调用它时可能看起来像这样:

(blah :specialthingy 0 body morebody lotsofbody)
(blah body morebody lotsofboy)
Run Code Online (Sandbox Code Playgroud)

我怎样才能做到这一点?请注意,我正在使用Clojure 1.2,所以我也使用新的可选关键字参数解构.我天真地尝试这样做:

(defmacro blah [& {specialthingy :specialthingy} & body])
Run Code Online (Sandbox Code Playgroud)

但显然这并不好.我怎样才能完成这个或类似的东西?

Mic*_*zyk 9

或许类似于以下内容(也可以看到如何定义defn其他宏clojure.core):

(defmacro blah [& maybe-option-and-body]
  (let [has-option (= :specialthingy (first maybe-option-and-body))
        option-val (if has-option (second maybe-option-and-body)) ; nil otherwise
        body (if has-option (nnext maybe-option-and-body) maybe-option-and-body)]
    ...))
Run Code Online (Sandbox Code Playgroud)

或者你可以更复杂; 如果您认为您可能希望在某些时候有多个可能的选项,那么这可能是值得的:

(defn foo [& args]
  (let [aps (partition-all 2 args)
        [opts-and-vals ps] (split-with #(keyword? (first %)) aps)
        options (into {} (map vec opts-and-vals))
        positionals (reduce into [] ps)]
    [options positionals]))

(foo :a 1 :b 2 3 4 5)
; => [{:a 1, :b 2} [3 4 5]]
Run Code Online (Sandbox Code Playgroud)