2017-01-09 27 views
0

我正在探索基本示例的宏,我不明白它是如何工作的。Clojure:为什么这个宏不起作用?

此:

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

不起作用。

我想:

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

没有运气...

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

你能说清楚吗? 预先感谢

回答

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)也返回nil,就像第一种变体。

+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))