我创建了一个宏,其定义如下:
(defmacro my-macro
[strategy & body]
...)
您可以像这样调用此宏:
(my-macro {:strategy "some"}
(do-something ..))
现在,我希望宏可选接受绑定。像这样:
(my-macro [my-value (load-value ..)]
{:strategy my-value}
(do-something ..))
所以我尝试将宏扩展为这样:
(defmacro my-macro
([strategy & body] `(my-macro [] ~routes ~body))
([bindings strategy & body]
...))
但这失败了:
java.lang.RuntimeException: Can't have more than 1 variadic overload
是否有一种很好的方法可以解决这个或推荐的方法?
答案 0 :(得分:3)
我的典型解决方法是检查传递给my-macro
的整个参数列表,并决定是否使用绑定:
(defmacro my-macro
[& body]
(let [bindings (if (vector? (first body)) (first body) [])
[strategy body*] (if (seq bindings) (rest body) body)]
`(let ~bindings
(do-something-with ~body* ~strategy))))
答案 1 :(得分:2)
我会提出这个:
(defmacro my-macro
{:arglists '([bindings? strategy & body])}
[bindings-or-strategy & more-args]
(let [[bindings strategy body] (if (vector? bindings-or-strategy)
[bindings-or-strategy
(first more-args)
(rest more-args)]
[[] bindings-or-strategy more-args])]
`(let ~bindings
(println :strategy ~strategy)
~@body)))
user> (my-macro [a 1] {:aaa :bbb} a)
:strategy {:aaa :bbb}
1
user> (my-macro {:aaa :bbb} 10)
:strategy {:aaa :bbb}
10
虽然它看起来比@ superkonduktr的答案更冗长,但对我来说它似乎更有用:它确保至少传递一个参数,并用:arglists