Macros 从符号列表构造clojure宏的正确方法是什么?

Macros 从符号列表构造clojure宏的正确方法是什么?,macros,clojure,Macros,Clojure,设想以下代码动态创建宏: (def a (list '+ 1 2)) (def b (list '- 10 5)) (def c (list '/ 22 2)) (defmacro gg [h] (let [k# `~h] k#)) 其目的是将符号向量传递给宏,对向量的每个元素进行计算,使其返回一个漂亮的宏形式,然后让宏将它们组合成一个漂亮的宏并对其进行计算。除了实际评估之外,上面的示例对所有项目都有效 当我运行它时,我得到: (gg [a b c]) => [(+ 1

设想以下代码动态创建宏:

(def a (list '+ 1 2))
(def b (list '- 10 5))
(def c (list '/ 22 2))

(defmacro gg [h]
  (let [k# `~h]
     k#))
其目的是将符号向量传递给宏,对向量的每个元素进行计算,使其返回一个漂亮的宏形式,然后让宏将它们组合成一个漂亮的宏并对其进行计算。除了实际评估之外,上面的示例对所有项目都有效

当我运行它时,我得到:

(gg [a b c])
=> [(+ 1 2) (- 10 5) (/ 22 2)]
传递一个符号列表并获得一个宏来计算它们的秘密是什么?我尝试了很多引用的组合,但还没有找到正确的组合

这个问题的真正目的是基于图中路径的定义构建查询。如果有人能举个例子,我将不胜感激

编辑:


我希望得到
11
而不是表单。

您不需要宏。宏不会执行您在这里寻找的操作。您要找的是
eval

(def a '/)
(def b 22)
(def c 2)
(eval (list* [a b c]))
=> 11
当然,如果需要,您可以编写一个宏,它可以扩展为
(eval(list*..)
。不过,它也可以是一个函数

这是从宏开始时非常常见的错误;试图编写一个取决于其参数的运行时值的宏。宏在编译时运行,通常在宏展开时,传递给宏的符号值还不可用

关于
eval
的使用,需要注意一些事项。没有人比保罗·格雷厄姆说得更好:

一般来说,在运行时调用eval不是一个好主意,原因有两个:

它的效率很低:eval得到一个原始列表,要么当场编译,要么在解释器中进行评估。任何一种方法都比预先编译代码并调用代码要慢。

它没有那么强大,因为表达式是在没有词汇上下文的情况下计算的。除此之外,这意味着您不能引用在被计算的表达式之外可见的普通变量。

通常,直接打电话给eval就像在机场礼品店买东西一样。等到最后一刻,你不得不为有限的二流商品选择支付高昂的价格。
(mapv评估[a b c]);[3 5 11]
我希望避免使用eval,因此尝试使用宏。顺便说一下,您的宏可以简化为(defmacro gg[h]h)(defmacro gg2[h]`(do~@h))(我不清楚)您想做什么。宏不计算它们的参数,因此不需要将引用形式传递给它们。他们确实评估了他们的结果。我决定尝试另一种被称为“函数”的语言特性,以获得良好的效果。谢谢你的解释。
(def a '/)
(def b 22)
(def c 2)
(eval (list* [a b c]))
=> 11