请在2024 Clojure现状调查!中分享您的想法。

欢迎!请参阅关于页面,了解更多关于它是如何工作的信息。

0投票
编译器

实例说明:clojure/tools.logging。

重现
- 对clojure/tools.logging(clojure.tools.logging & clojure.tools.logging.impl)中的所有命名空间进行AOT编译
- 将结果放在类路径上,然后对clojure/java.data(clojure.java.data)进行AOT编译
- 观察第二次编译的输出中的clojure/tools.logging$eval32$fn__33.class(确保为两次编译有不同的输出目录)。

这通常是无害的,但如果您尝试缓存AOT编译输出,就会变成一个问题。当您通过这种方式尝试缓存之前的AOT运行时,有时会得到两个本来不相关的命名空间生成相同的文件名。如果它们有相同的内容,那就没问题,但是没有保证它们有相同的内容(因为32 & 33只是(gensym))。根据类路径中的哪一个“获胜”,这可能会导致不良后果。

我不是这方面的专家,但是这些“额外”的类最好作为工具.logging的一部分生成,或者以某种方式别名到它们编译的命名空间中(例如,clojure/java/data/$clojure$tools$logging$eval32$fn__33.class或clojure/tools/logging/$clojure$java$data$eval32$fn_33.class)。

2 答案

0投票

由hiredman发表的评论

tools.logging使用eval在某些类存在于类路径上时生成一些代码,eval生成类文件,当您打开AOT编译时,这些类文件将被输出到文件系统中。

名称之所以是这样的,是因为eval发生在tools.logging命名空间加载时,所以ns var的值是tools.logging命名空间,这就是编译器从其中生成名称的原因。

0投票
by
参考:https://clojure.atlassian.net/browse/CLJ-1916(由 alex+import 报告)
...