我有两个不同的Clojure宏,但基于操作(〜@和〜),我需要引用输入或不引用。
(defmacro make2 [t]
`(list 1 ~@t))
(defmacro make3 [t]
`(list 1 ~t))
(make2 (1 2 3)) -> (1 1 2 3)
(make3 '(1 2 3)) -> (1 (1 2 3))
这是为什么?我可以猜测,使用宏,不会评估参数(这就是为什么make2不会导致错误)。但是在获得参数之后,我不确定处理它们的逻辑。
答案 0 :(得分:2)
(macroexpand-1 '(make2 (1 2 3)))
;; ==> (clojure.core/list 1 1 2 3)
(macroexpand-1 '(make3 (1 2 3)))
;;==> (clojure.core/list 1 (1 2 3))
~@
将列表(1 2 3)
拼接到表达式(list 1 ...)
中,然后计算结果表达式,即使用参数list
计算函数1 1 2 3
。 Clojure会评估每个参数,但当然,数字会自行评估。
~
只需将参数(1 2 3)
插入(list 1 ...)
作为其第二个参数,然后评估整个表达式,同时评估每个参数list
。当它发生时,Clojure看到第二个参数中有一对未加引号的括号,并假设左括号后面的第一个表达式是一个函数(或宏)。也就是说,Clojure假设1
的内部实例是一个函数,它不是。这就是你得到例外的原因
ClassCastException java.lang.Long cannot be cast to clojure.lang.IFn ...
表示长整数不能转换为函数。