请分享您的想法在 2024 Clojure 状态调查!

欢迎!请参阅 关于 页面,以获取更多关于如何使用本站的信息。

+1

我试图在宏函数中创建一个原子并在宏输出形式中嵌入对其的引用

(defmacro x []
  (let [a (atom {})]
    `(fn []
       ~a)))

使用此宏尝试的结果是出现以下错误

`

(x)
Syntax error compiling fn* at (/tmp/form-init15982565344292085756.clj:1:1).
Can't embed object in code, maybe print-dup not defined: clojure.lang.Atom@350e9f50

`

我尝试定义一个空的 print-dup 覆载,但它导致了不同的错误

`

(defmethod print-dup clojure.lang.Atom [x w])
(x)
Syntax error compiling fn* at (/tmp/form-init15982565344292085756.clj:1:1).
Can't embed unreadable object in code: clojure.lang.Atom@5f3623b3

`

考虑到 Clojure 有 eval,我本以为它会正常工作。这里的问题是什么?

1 个回答

+2

被选中
 
最佳答案

宏是接受代码并返回代码的函数。原子是具有状态的对象 - 无法在代码中用身份表示它们,因此这行不通。

您真正想要做什么?


修改了
>宏是一个函数,它接收代码并返回代码。原子是具有状态的对象 - 由于它们在代码中无法以标识符的形式表示,所以这将是无效的。

我不确定我是否理解了你的意思。

>你实际上想要做什么?

该宏将返回一个函数,该函数在评估时会修改原子值,其他代码将读取这些值。这是一个更好的例子

  (defmacro x []
    (let [a (atom {})
        s (gensym)]
    `(fn []
         (let [~s ~a]
         ))))
以上示例与下面哪个不同?

(defmacro x []
  (let [a (vec (range 3))
        s (gensym)]
    `(fn []
       (let [~s ~a]
        ))))

后者是有效的。
在你的第二个示例中,a 和 s 都有代码表示(作为一个矢量和符号)。原子是具有标识和状态的对象,这不是。

总的来说,在编译时构造对象然后在运行时使用(如aot编译可能完全分开这些)通常没有意义。

你可以将原子的构造移动到生成的代码中(在`内部),这样你就是在生成运行时构造的代码。但我不是很清楚这个宏的其他部分有何作用。

您真正想要做什么?
...