【问题标题】:Using variadic macro arguments as a list使用可变参数宏参数作为列表
【发布时间】:2016-09-27 00:22:16
【问题描述】:

我试图写一个宏来比较多个表达式的运行时间,结果碰壁了。我的问题可以浓缩为以下代码:

(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 作为函数调用,这显然是错误的。

如何映射宏中的可变参数列表?

【问题讨论】:

    标签: clojure macros variadic-macros


    【解决方案1】:

    我在写这个问题的时候就想出来了,所以我想我会发布一个答案,以防将来有人被困在这里。

    参数列表需要先强制成列表表示,否则将被评估为表单。这可以像这样完成:

    (defmacro test-m [& exprs]
      `(map #(.toString %) (list ~@exprs))
    

    注意exprs 通过@ 扩展,并提供给list。 (感谢@amalloy 的更正)。

    明显是回顾,但它让我坚持了一段时间。希望这对某人有所帮助。

    【讨论】:

    • 你可能不想引用它,而是写(list ~@exprs)~(vec exprs)
    • @amalloy 到底有什么不同?引用它似乎更直接。我不是要争论。我很好奇。
    • 尝试使用 x y z 变量而不是 1 2 3 常量。
    • @amalloy 哎呀!谢谢。很好的收获。
    猜你喜欢
    • 2019-09-03
    • 2018-01-13
    • 1970-01-01
    • 2012-12-31
    • 1970-01-01
    • 2010-10-15
    • 2011-09-11
    • 1970-01-01
    • 2013-05-21
    相关资源
    最近更新 更多