此问题基于this answer的限制。
如果我有一个使用拼接unquote的宏,请执行以下操作:
(defmacro instantiate [klass values]
`(new ~klass ~@values))
仅当values
是文字序列或seq-able时才会起作用。
如果传递了一个包含如下序列的var:
(def v [1 2 3])
(macroexpand '(instantiate Person v))
然后输出将是一个错误,表明v
不是序列。
即使函数调用也会被解释为列表:
(defn vf [] [1 2 3])
(macroexpand '(instantiate Person (vf)))
user=>(new Person vf)
我的问题是:在那两个要拼接的序列不是文字的情况下,有没有办法在Clojure宏中使用拼接取消引用?
答案 0 :(得分:2)
宏接收的参数未经评估,因此您看到的行为符合预期。
宏在编译时扩展,而不是在运行时扩展。传递给宏的任何变量的值可能在编译时不可用,因此使用eval
之类的脏操作在一般情况下将不起作用。不要创建需要这些技巧的宏。
答案 1 :(得分:1)
拼接引号在几乎所有情况下都节省了很多时间,除非它们不工作,那么你需要用老式的方式做事......
(defmacro instantiate [klass values]
`(new ~klass ~@values))
可能会成为
(defmacro instantiate [klass values]
(concat (list 'new klass) (if (seq? values)
values
(list values))))
user=> (macroexpand '(instantiate asdf (1 2 3)))
(new asdf 1 2 3)
user=> (macroexpand '(instantiate asdf 1))
(new asdf 1)