【发布时间】:2015-05-25 00:34:49
【问题描述】:
我有一个文件,其中包含一些受信任的 clojure 源代码:
((+ a b) (* a b) (- a b))
对于列表中的每一项我想生成一个匿名函数:
(fn [a b] (+ a b))
(fn [a b] (* a b))
(fn [a b] (- a b))
如果我调用下面的马可
(defmacro create-fn
[args exprs]
`(fn ~args ~exprs))
直接使用一些 clojure 代码就可以完美运行:
user=> (macroexpand-1 '(create-fn [a b] (* a b)))
(clojure.core/fn [a b] (* a b))
但是当我将文件的上下文绑定到本地并尝试映射我的宏时,它将不起作用。在访问第一个生成的函数时,我收到错误消息“java.lang.RuntimeException: Unable to resolve symbol: a in this context”
(请注意,我必须在宏中添加一个额外的eval 来获取符号e 的值,该符号在map 使用的匿名函数中使用)
(defmacro create-fn
[args exprs]
`(let [e# (eval ~exprs)]
(fn ~args
e#)))
(let [exprs (read-string "((+ a b) (* a b) (- a b))")
fns (map
(fn [e] (create-fn [a b] e))
exprs)]
(first fns))
非常感谢任何帮助!
【问题讨论】:
-
exprs绑定(+ a b),你调用eval就可以了,报错是正确的 -
如果我在宏
create-fn中添加(println exprs),它会打印“e”。我的理解是,在宏扩展期间,exprs绑定到符号e,而不是它的值。因此,我认为我需要在exprs上调用eval以产生符号e的值...