我正在探索基本示例的宏,我不明白它是如何工作的。Clojure:为什么这个宏不起作用?
此:
(defmacro evalf [f v]
(f v))
(evalf + 2)
不起作用。
我想:
(defmacro evalf [f v]
'(f v))
(evalf + 2)
没有运气...
我不明白其他语法:~~ @等等,但他们也不管用。我看到符号f没有指向+,但我不知道要说“取f是+的值”。
你能说清楚吗? 预先感谢
我正在探索基本示例的宏,我不明白它是如何工作的。Clojure:为什么这个宏不起作用?
此:
(defmacro evalf [f v]
(f v))
(evalf + 2)
不起作用。
我想:
(defmacro evalf [f v]
'(f v))
(evalf + 2)
没有运气...
我不明白其他语法:~~ @等等,但他们也不管用。我看到符号f没有指向+,但我不知道要说“取f是+的值”。
你能说清楚吗? 预先感谢
取决于你想做的事做有两个变种:
第一个(你可能想要的)是:
(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
,就像第一种变体。
尝试
(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))
谢谢,都是答案,但我更了解你的,所以我选择了这个 –