我有两个宏.第一个将符号作为唯一参数(因为它传递给def,需要一个符号).第二个函数采用符号列表,并应分别使用每个符号调用第一个符号.
(defmacro m1 [s]
'(let [f# ... dynamic function definition ...]
(def ~s f#))
Run Code Online (Sandbox Code Playgroud)
第二个宏应该采用符号列表并将它们传递给第一个,但我无法使它工作.我能想到的最好的是以下内容:
(defmacro m2 [symbols]
`(for [s# ~symbols] (eval (read-string (str "(name.of.current.namespace/m1 " s# ")")))))
Run Code Online (Sandbox Code Playgroud)
它s#会在传递给第一个宏之前强制进行评估.它还使用字符串列表调用,而不是符号列表.
这对于我正在使用的库非常有用,库中的所有函数都使用相同的两个第一个参数.我试图在我的命名空间中为某些函数创建包装函数,这些函数自动提供所有这些函数共有的前两个参数值.
有什么想法来改善这个吗?
通常当你问如何让两个宏合作时,答案是不要让它们都成为宏.我认为我关于宏编写宏的博客文章将有助于澄清.对于这种特殊情况,我可能会结合评论中的两条建议:
(defmacro build-simpler-functions [& names]
(cons 'do
(for [name names]
`(def ~(symbol (str "simple-" name))
(partial ~name 5 10))))) ; if you always pass 5 and 10
(build-simpler-functions f1 f2)
Run Code Online (Sandbox Code Playgroud)
这扩展到
(do
(def simple-f1 (clojure.core/partial f1 5 10))
(def simple-f2 (clojure.core/partial f2 5 10)))
Run Code Online (Sandbox Code Playgroud)
看起来基本上就是你想要的.
编辑:如果你"总是"传递的参数对于每个函数都不同,你可以这样做:
(defmacro build-simpler-functions [& names]
(cons 'do
(for [[name & args] names]
`(def ~(symbol (str "simple-" name))
(partial ~name ~@args)))))
(build-simpler-functions [f1 5 10] [f2 "Yo dawg"]) ; expansion similar to the previous
Run Code Online (Sandbox Code Playgroud)