我正在尝试(作为自学练习)创建Clojure宏,该宏将生成代码以将函数应用于整数序列并求和结果,例如
f(0)+ f(1)+ f(2)+ f(3)
这是我的尝试:
(defmacro testsum [func n]
`(fn [x#] (+ ~@( map (fn [i] `(~func x#)) (range n)))))
但是x#gensym似乎出了问题,我最终得到了x的两个不同版本,因此该功能无法正常工作:
(macroexpand '(testsum inc 3))
给出:
(fn* ([x__809__auto__]
(clojure.core/+
(inc x__808__auto__)
(inc x__808__auto__)
(inc x__808__auto__))))
除了x ...的不同809和808版本外,这几乎就是我想要的。
我究竟做错了什么?我以为auto gensym就是为了实现这种目的而创建一个唯一的符号?有更好的方法吗?
最佳答案
foo#
-style gensyms仅在创建它们的语法引用内有效。在您的代码中,两个x#
是在不同的语法引用块中创建的:
(defmacro testsum [func n]
`(fn [x#] (+ ~@( map (fn [i] `(~func x#)) (range n)))))
^- s-q1 ^-unquote ^- s-q2
要解决此问题,请使用显式的
(gensym)
调用:(defmacro testsum [func n]
(let [x (gensym "x")]
`(fn [~x] (+ ~@(map (fn [i] `(~func ~x)) (range n))))))
和宏扩展(
(macroexpand '(testsum inc 3))
):(fn* ([x4966] (clojure.core/+ (inc x4966) (inc x4966) (inc x4966))))
关于code-generation - 在Clojure宏中控制符号生成,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/2840119/