2024 State of Clojure 问卷调查中分享您的看法!

欢迎!请查阅关于页面以了解此工作的更多信息。

+1
编译器
已关闭

在将 lazy-seq 传递到 quote 时遇到了错误。以下示例将导致此问题。

`
user=> (eval `(quote ~(lazy-seq '(1 2 3))))
(1 2 3)

user=> (eval `(quote ~(lazy-seq '())))
语法错误(UnsupportedOperationException)编译 fn* 在(REPL:1:1)。
未知集合类型

user=> (eval (quote ())) () ``

1 答案

0

是否存在某种场景与此相关?

Clojure 的很多方法都会返回一个惰性序列,如果在对一个空集合使用quote时,可能会引发这个问题。例如:"`(quote ~(map a b))"。

我直接使用惰性序列写上述例子是为了创建一个最小测试用例。
我不曾听闻任何人遇到过这个问题,因此我更感兴趣的是在何时(比如像你这样的用户)可能会实际遇到它。
是否有任何不涉及eval的情景会导致问题?因为eval在生产Clojure代码中出现的频率极低。
"(defmacro m [] `'~(keep (constantly nil) (range 10)))"也存在同样的问题。

我发现`Compiler$EmptyExpr`除了空列表外,并不正确地处理空序列。也许这个附近的 Compiler 代码https://github.com/clojure/clojure/blob/6975553804b0f8da9e196e6fb97838ea4e153564/src/jvm/clojure/lang/Compiler.java#L2990-L2991应该处理这些情况。

编辑
我有一个宏,它使用quote将一些数据记录到数据结构中。这类似于 "(defmacro m [x y] `(swap! global-data assoc ~(foo x) (quote ~(map bar y))))"
问题是当“y”传入一个空向量时触发的。

我现在通过将映射的懒序列转换为向量来绕过这个问题。
"(defmacro m [x y] `(swap! global-data assoc ~(foo x) (quote ~(vec (map bar y)))))"
谢谢,这很有帮助
...