gpt4 book ai didi

Clojure 宏难题 : expanding sequence in macro args

转载 作者:行者123 更新时间:2023-12-02 14:41:28 24 4
gpt4 key购买 nike

这不是我的“生产代码”,而是出于说明目的对问题的简化。另外,这个问题的标题具有误导性,因为它让人想起 ~@ 扩展,我理解这一点,但这可能不一定是问题。如果可以的话,请建议一个更好的问题标题。

给定一个具有以下形式的宏:

(defmacro my-add [x & ys] `(+ ~x ~@ys))

现在假设我们有一个列表:

(def my-lst '(2 3))

现在我想要一个使用 my-add 的函数,我可以将 my-lst 作为参数传递给它,即

(call-my-add 1 my-lst)

我以看似显而易见的方式定义了该函数:

(defn call-my-add [x ys]
(apply my-add (cons x ys)))

但是:

java.lang.Exception: Can't take value of a macro: #'user/call-my-add (repl-1:60)

我尝试了各种疯狂的技巧来使用 eval、apply 甚至将 call-my-add 定义为宏来使 call-my-add 函数正常工作,但它们都会给出类似的 ClassCastExceptions。

有什么办法可以解决这个问题吗?

最佳答案

没有。宏不会、不能、永远不会访问其参数中包含的实际运行时值,因此无法将它们拼接到扩展中。他们得到的只是您传递给他们的符号,在本例中为 my-list。 “解决这个问题的方法”是将 my-add 定义为函数,然后(可选)使用一个宏来调用该函数以生成其代码。

我写了一个blog post最近,您可能会发现这一点很有启发。

如果您愿意,您可以使用 evals 来完成此操作,但几乎在所有情况下这都是一个糟糕的主意:

(let [my-list '(1 2)]
(eval `(my-add 5 ~@my-list)))

关于Clojure 宏难题 : expanding sequence in macro args,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5277451/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com