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

Jos*_*ine 1 macros clojure

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

这个 :

(defmacro evalf [f v]
  (f v))
(evalf + 2)
Run Code Online (Sandbox Code Playgroud)

不起作用。

我试过 :

(defmacro evalf [f v]
  '(f v))
(evalf + 2)
Run Code Online (Sandbox Code Playgroud)

没运气...

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

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

lee*_*ski 5

根据您想要做什么,有两种变体:

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

(defmacro evalf [f v] `(~f ~v))
Run Code Online (Sandbox Code Playgroud)

或者

(defmacro evalf [f v] (list f v))
Run Code Online (Sandbox Code Playgroud)

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

第二个是这样的:

(defmacro evalf [f v] ((resolve f) v))
Run Code Online (Sandbox Code Playgroud)

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

您的变体 with(f v)静默失败,因为当您调用 时(evalf + 10)+此处只是一个普通符号,而不是从宏的角度对函数的引用,因此它尝试调用('+ 10),因为 clojure 中的符号具有函数的语义,这是完全正确的语法,但此调用会生成nil. (符号调用的例子:('+ {'+ 10})=> 10)所以如果你想得到这个函数,命名为这个符号,你必须解析它,就像我的第二个例子。

变体 with '(f v)just 扩展为两个符号的列表 : 'fand 'v,然后导致运行时调用('f 'v)也返回nil,就像第一个变体一样。