2024年Clojure状态调查中分享您的看法!

欢迎!请参阅关于页面获取更多有关此功能的信息。

+6
编译器
编辑

Clojure编译器生成的类名可以任意长,超过文件系统允许的最大文件名长度。例如,当您嵌套函数太深时就会发生这种情况

(defmacro nestfn [n & body]
  (if (> n 0)
    `(fn [] (nestfn ~(- n 1) ~@body))
    body))

(def myf (nestfn 100 "body"))

编译此代码将引发{{java.io.IOException: 文件名太长}}异常。

这个问题不太好找到,可能是因为它没有提到或标记core.match,尽管这是更常见的罪魁祸首之一。

有任何进展吗?该工单已标记为“关键”。
我已标记了它。它不在我们1.12的列表中,但我已经在我们1.13的列表中查看过了。

10 答案

0

评论者:martinraison

Scala 社区在一段时间前发现了这个问题,现在编译器有一个 {{max-classfile-name}} 参数(默认为 255)。在超过限制时使用哈希。我们也许应该考虑类似的东西?

0

评论者:panewman

我在 Windows 下使用 13 个 clojure.core.match 模式时遇到了编译失败的问题。我认为这是问题的根本原因。

0

_评论者:chrisbetz

关于此的一些更多信息

我的一个同事因为使用 Linux / eCryptfs(相比于我们通常使用的加密 macOS FileVault,这里的限制(143)相当小)遇到了这个问题:请参考https://bugs.launchpad.net/ecryptfs/ bug/344878

然而,Clojure 并不是唯一遇到此类问题,Scala 也遭受重创:请参考https://issues.scala-lang.org/browse/SI-3623

对此并没有“简单”的解决方案,像 Scala 那样截断文件名显然会带来很多其他问题。

对于所有受到此问题困扰的用户,一个可能的解决方案可能是 Mario Pastorelli 在https://issues.scala-lang.org/secure/ViewProfile.jspa?name=melrief) 在评论https://issues.scala-lang.org/browse/SI-3623?focusedCommentId=76104&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-76104

使用未加密的文件系统临时存储类文件,也许可以通过有一个 tempFS 来在内存中保存东西。这不是最好的方法,因为我们不喜欢将重要信息留得未加密...

0

评论者:alexvong1995

你好,

我在使用 clojure.core.match 时遇到了相同的问题。我宏展开函数定义,并观察到宏展开的定义非常嵌套。

我认为解决这个问题的一种方法是为类文件提供一个选项,将其包装为 jar 文件,并使用一些更短的文件名,这样类名可以保持不变(zip 文件的名称可以任意长,对吗?)。你怎么看?

顺便提一下,我在使用 clojure 1.9.0,所以我认为我们应该说这个问题也会影响 1.9。

0

评论者:alexvong1995

我提出了一个概念验证补丁。当类名长度超过255时,编译器现在输出jar而不是class。jar名仅仅是类名的简单(左)截断。

假设 **compile-path* 是设置为 "build",那么你需要在你的类路径中添加 build/,以便能够找到jar文件。

这个补丁只是一个概念证明,理想情况下,所有具有长名的类都应该放在一个大的jar文件中,以避免需要解压缩许多文件。此外,用户应该能够指定 **compile-name-max** 和 **compile-jar-name**。最后,代码相当丑陋,我应该将它们分开成几个函数。

0

评论者:alexmiller

Alex - 我们不会输出jar。这与Clojure运行时的许多方面相冲突。

0

评论者:[email protected]

如果这个评论离题了,我表示抱歉。但原始示例对我来说有点令人困惑。也许它应该是

`
(defmacro nestfn [n & body]
(if (> n 0)

`(fn [] (nestfn ~(dec n) ~@body))
`(do ~@body)))

`

这样 {{(trampoline (nestfn 10 "foo"))}} 会返回 "foo"。然而,当 n=1000 在macOS上时,我确实得到了一个 CompilerException java.lang.StackOverflowError。

0

评论者:gsnewmark

@Alex Miller 你好!采用类似Scala的方法(在名称过长时进行名称哈希)修补程序会被考虑吗?这会破坏二进制兼容性,这个解决方案默认会禁用,但可以通过使用新的编译器选项来启用名称哈希。这个方法肯定有助于我们特定的案例,但我不确定是否足够有用和通用,可以通过编译器来包含,所以我还没有开始编写修补程序。

0
评论者:alexmiller

不会进行任何破坏性更改。计划应该是当当前策略不起作用时切换到第二策略。
0
参考:https://clojure.atlassian.net/browse/CLJ-1852(由 alex+import 报告)
...