我正在尝试编写一个比较多个表达式的运行时间的宏,然后碰到了一堵墙。我的问题可以压缩为以下代码:
(defmacro test-m [& exprs]
`(map #(.toString %) ~exprs))
如果我将其称为(test-m 1 2 3)
,我希望这会产生以下代码:
(map #(.toString %) [1 2 3])
哪个完全有效。不幸的是,这实际上会导致错误:
ClassCastException java.lang.Long无法强制转换为clojure.lang.IFn helpers.general-helpers / eval663(NO_SOURCE_FILE:76)
我可以看到可能发生这种情况的唯一方法是& exprs
会导致(1 2 3)
,然后会尝试将1
作为函数调用,这显然是错误的。
如何映射宏中的可变参数列表?
答案 0 :(得分:3)
我在写这个问题时想通了,所以我想我会发一个答案,以防将来其他人被困在这里。
参数列表需要先强制进入列表代理,否则它将被评估为表单。这可以这样做:
(defmacro test-m [& exprs]
`(map #(.toString %) (list ~@exprs))
注意exprs
通过@
展开,并提供给list
。 (感谢@amalloy的纠正)。
显然是回顾,但它让我有一段时间。希望这有助于某人。