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

时间:2015-02-21 12:01:13

标签: macros 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))

返回:

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

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

(我认为这是与已经提出的其他地图/宏问题不同的问题,因为这是关于 嵌套 参数检索)。

1 个答案:

答案 0 :(得分:3)

宏在编译时展开。

(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做它的事情时,没有宏。

宏在运行之前更改代码。它的目的是降低复杂性和代码大小,但它增加了一些混乱,因为读取代码的程序员需要了解她正在阅读的代码库中的自定义宏。保罗格雷厄姆在On Lisp中建议你可能必须使用这个宏十到二十次才能在可读性方面产生净改善。