Clojure:为什么这个宏不起作用?

时间:2017-01-09 11:06:32

标签: clojure macros

我正在使用基本示例探索宏,但我不明白它是如何工作的。

这:

(defmacro evalf [f v]
  (f v))
(evalf + 2)

不起作用。

我试过了:

(defmacro evalf [f v]
  '(f v))
(evalf + 2)

没有运气......

我不懂其他语法:~~ @等等,但它们也不起作用。我看到符号f没有指向+但是我不知道说"取f的值是+"。

你能说得更清楚吗? 提前致谢

2 个答案:

答案 0 :(得分:4)

尝试

(defmacro evalf [f v]
  (list f v))

(evalf (partial * 2) 66); 132

致电evalf

  • 参数未经评估为表单 (partial * 2)66;
  • 宏的主体产生表达式 (list '(partial * 2) '66);
    • ,其评估格式为((partial * 2) 66)
    • 从宏返回的
    • 评估为132

使用语法引用的替代方法是

(defmacro evalf [f v]
  `(~f ~v))

答案 1 :(得分:4)

根据您的目的,有两种变体:

第一个(你可能想要的那个)是:

(defmacro evalf [f v] `(~f ~v))

(defmacro evalf [f v] (list f v))

他们都做同样的事情:生成你需要的s表达式。 有了这个,(evalf + 10)将在编译时扩展到(+ 10),然后在运行时成功评估。

第二个是:

(defmacro evalf [f v] ((resolve f) v))

现在函数f在编译时将称为,因此宏将扩展为结果:10

(f v)的变体无声地失败,因为当您致电(evalf + 10)时, +这里只是一个简单的符号,而不是从宏的角度来看函数的引用,因此它试图调用('+ 10),因为clojure中的符号具有函数的语义,它是完全正确的语法,但此调用产生nil。 (符号调用的示例:('+ {'+ 10}) => 10)因此,如果您想获得名为此符号的函数,则必须解决它,如我的第二个示例所示。

带有'(f v)的变体只会扩展为两个符号的列表:'f'v,然后导致运行时调用('f 'v)也返回{{ 1}},就像第一个变种一样。