在clojure中,如何从另一个宏评估宏的参数?

Pie*_*eed 8 macros clojure

我有两个宏.第一个将符号作为唯一参数(因为它传递给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#会在传递给第一个宏之前强制进行评估.它还使用字符串列表调用,而不是符号列表.

这对于我正在使用的库非常有用,库中的所有函数都使用相同的两个第一个参数.我试图在我的命名空间中为某些函数创建包装函数,这些函数自动提供所有这些函数共有的前两个参数值.

有什么想法来改善这个吗?

ama*_*loy 8

通常当你问如何让两个宏合作时,答案是不要让它们都成为宏.我认为我关于宏编写宏的博客文章将有助于澄清.对于这种特殊情况,我可能会结合评论中的两条建议:

(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)