假设我有以下关键字数组
(def keys [::description ::url ::mailing-list])
我想在两个规格中重复使用;一个用于定义一个映射,另一个用于定义函数的可选参数。
(require '[clojure.spec :as spec])
(spec/def ::project-map
(spec/keys :opt-un keys))
(spec/def ::project-args
(spec/keys* :opt-un keys))
问题是,keys
和keys*
会传递带引号的符号'keys
而不是它所引用的变量中保存的已解析值。
所以我的问题是:是否可以像读取常见的lisp #.
读取器宏一样在读取时解析键的值,或者如果宏获取符号,则必须重新定义宏以解析符号列表文字?
答案 0 :(得分:1)
您可以使用eval
:
(spec/def ::project-map
(eval `(spec/keys :opt-un ~keys)))
(spec/def ::project-args
(eval `(spec/keys* :opt-un ~keys)))
这是通过对clojurians松弛的建议。
答案 1 :(得分:1)
您也可以将它们包装在另一个宏中,因为宏负责评估它们的参数。
(defmacro def-both [name name* keys]
`(do (s/def ~name (s/keys :opt-un ~keys))
(s/def ~name* (s/keys* :opt-un ~keys))))
(user/def-both ::project-map ::project-args [::description ::url ::mailing-list])
答案 2 :(得分:0)
或者你可以这样做:
(spec/def ::project-map (spec/keys ::opt-un ~keys))
可能需要使用合格的命名空间(例如::opt-un
)
spec/def
已经是一个宏;)