在Clojure宏中引用基于〜和〜@的选择
我有两个不同的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不会导致错误)。 然而,在获得参数后,我不确定处理它们的逻辑。
(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 ...)
,然后评估结果表达式,即用参数1 1 2 3
评估函数list
。 Clojure评估每个参数,但当然,数字会自己评估。
~
只需将参数(1 2 3)
插入(list 1 ...)
作为其第二个参数,然后评估整个表达式,并将每个参数评估为list
。 当它发生时,Clojure发现第二个参数中有一对未加引号的括号,并假定该左括号之后的第一个表达式是一个函数(或宏)。 也就是说,Clojure假定1
的内部实例是一个函数,不是。 这就是为什么你会得到例外
ClassCastException java.lang.Long cannot be cast to clojure.lang.IFn ...
其中说长整数不能转换成函数。
链接地址: http://www.djcxy.com/p/65763.html