我想写一个宏来接受一个向量参数
(defmacro eval-verify [body]
`(cond
~@body
:default nil))
在这种情况下适用
(eval-verify [true 1 false 2])
它返回1,我运行
(macroexpand-1 '(eval-verify [true 1 false 2]))
它返回
(clojure.core/cond true 1 false 2 :default nil)
看起来没问题,但是当我确定一个向量时
(def a [true 1 false 2])
并运行
(eval-verify a)
是错误
IllegalArgumentException Don't know how to create ISeq from: clojure.lang.Symbol
如何编写宏可以接受符号的参数,或写函数可以做同样的事情。
答案 0 :(得分:4)
宏参数作为未评估的符号传递。因此,当您调用(eval-verify a)
符号时,a是传递给eval-verify
而不是[true 1 false 2]
的body参数的值。由于unquote-splice(〜@)需要Seq并且它找到符号(a),因此会收到IllegalArgumentException。
您需要使用(eval-verify [true 1 false 2])
形式调用eval-verify,否则您需要使用普通函数。
您可以使用以下功能代替宏:
(defn eval-verify [coll]
(loop [[f v :as c] coll]
(cond
(and (ifn? f) (f)) v
(and (not (ifn? f)) f) v
:else (if (seq c) (recur (drop 2 c)) nil))))