如何在 Clojure 中的映射函数内的宏中获取嵌套参数?

How do I get the nested argument in a macro inside a mapped function in Clojure?

我正在将我的宏传递给地图操作。我在表达自己的价值观时遇到了一些麻烦。这是一个例子:

(def num-vec [1 2 3 4 5])

(defmacro describe-args [first-arg]
  `(println '~first-arg " = " ~first-arg))

(doall (map #(describe-args (+ 42 %)) num-vec))

这个returns:

(+ 42 p1__437#)  =  43
(+ 42 p1__437#)  =  44
(+ 42 p1__437#)  =  45
(+ 42 p1__437#)  =  46
(+ 42 p1__437#)  =  47

我的问题是:如何在 Clojure 中的映射函数内的宏中获取嵌套参数?

(我相信这是一个与其他 map/macro 问题不同的问题,因为这是关于 nested 参数检索).

宏在编译时展开。

(doall (map #(describe-args (+ 42 %)) num-vec))

扩展为:

(doall (map (fn [tmpvarname] 
              (describe-args (+ 42 tmpvarname))
            num-vec))

tmpvarname 是唯一的,每次展开宏时都会发生变化。然后代码进一步扩展:

(doall (map (fn [tmpvarname] 
              (println '(+ 42 tmpvarname) " = " (+ 42 tmpvarname))) 
            num-vec))

这是在代码执行之前完成的,宏扩展器不知道 num-vec 是什么,除了是一个变量符号。实际上它不知道 mapprintln 是什么,因为在宏扩展时代码是数据。 map只是一个符号。

现在,当这段代码是 运行 时,运行时间不需要知道那里曾经有一个宏开始。当 map 执行它的操作时,没有宏。

宏在 运行 之前更改代码。它的目的是降低复杂性和代码大小,但它增加了一些混乱,因为阅读代码的程序员需要了解她正在阅读的代码库中的自定义宏是什么。 Paul Graham 在 On Lisp 中建议您可能必须使用该宏十到二十次才能在可读性方面产生净改进。