使用可变宏参数作为列表
Using variadic macro arguments as a list
我正在尝试编写一个宏,将多个表达式的 运行 次和 运行 比较成一堵墙。我的问题可以浓缩为以下代码:
(defmacro test-m [& exprs]
`(map #(.toString %) ~exprs))
如果我这样称呼它 (test-m 1 2 3)
,我希望它会生成如下代码:
(map #(.toString %) [1 2 3])
完全正确。不幸的是,这实际上会导致错误:
ClassCastException java.lang.Long cannot be cast to clojure.lang.IFn helpers.general-helpers/eval663 (NO_SOURCE_FILE:76)
我能看到这可能发生的唯一方法是如果 & exprs
导致 (1 2 3)
,然后它将尝试将 1
作为函数调用,这显然是错误的。
如何映射宏中的可变参数列表?
我在写问题的时候弄明白了,所以我想我会 post 一个答案,以防将来其他人被困在这里。
参数列表需要先强制为列表表示,否则将被评估为表单。这可以像这样完成:
(defmacro test-m [& exprs]
`(map #(.toString %) (list ~@exprs))
请注意 exprs
通过 @
扩展并提供给 list
。 (感谢@amalloy 的更正)。
显而易见的是回想起来,但它让我停滞了一段时间。希望这对某人有所帮助。
我正在尝试编写一个宏,将多个表达式的 运行 次和 运行 比较成一堵墙。我的问题可以浓缩为以下代码:
(defmacro test-m [& exprs]
`(map #(.toString %) ~exprs))
如果我这样称呼它 (test-m 1 2 3)
,我希望它会生成如下代码:
(map #(.toString %) [1 2 3])
完全正确。不幸的是,这实际上会导致错误:
ClassCastException java.lang.Long cannot be cast to clojure.lang.IFn helpers.general-helpers/eval663 (NO_SOURCE_FILE:76)
我能看到这可能发生的唯一方法是如果 & exprs
导致 (1 2 3)
,然后它将尝试将 1
作为函数调用,这显然是错误的。
如何映射宏中的可变参数列表?
我在写问题的时候弄明白了,所以我想我会 post 一个答案,以防将来其他人被困在这里。
参数列表需要先强制为列表表示,否则将被评估为表单。这可以像这样完成:
(defmacro test-m [& exprs]
`(map #(.toString %) (list ~@exprs))
请注意 exprs
通过 @
扩展并提供给 list
。 (感谢@amalloy 的更正)。
显而易见的是回想起来,但它让我停滞了一段时间。希望这对某人有所帮助。