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

欢迎!请参阅关于页面获取更多关于此 hoe 如何工作的小信息。

+6
编译器
编辑

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

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

(def myf (nestfn 100 "body"))

编译此代码会抛出{{java.io.IOException: File name too long}}异常。

这个问题很难找到,可能是因为它没有提到或标记core.match,尽管那是更为常见的错误原因之一。

有没有进展?该工单被标记为“关键”。
我已添加标记。它不在我们的1.12列表中,但我在1.13的列表中都考虑到了。

10 条回答

0

评论者:martinraison

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

0

评论者:panewman

我尝试了在 Windows 下使用 clojure.core.match 和 13 种模式,但编译失败。我假设这是问题的根本原因。

0

_评论者:chrisbetz

关于该信息的更多信息

我的一个同事遇到这个问题是因为他使用 Linux / eCryptfs(与否则使用我们的 FileVault 加密的 macOS 相比的 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文件,并使用一个较短的文件名,这样类名就可以保持不变(压缩文件的名称可以尽可能长,对吧?)。您觉得怎么样?

顺便说一句,我正在使用clojure 1.9.0,所以我认为我们应该说这个bug也影响1.9版本。

0
by

评论者:alexvong1995

我想出一个概念验证补丁。因此,当类名长度超过255时,编译器现在会输出jar而不是class文件。jar的名称只是类名的一个(左)截断。

假设**compile-path***设置为"build",那么您需要将build/**添加到您的类路径中,以便可以找到jar文件。

这个补丁只是一个概念验证,理想情况下,所有长名称的类都应放入一个大jar中,以避免解压多个文件。此外,用户应能够指定**compile-name-max**和**compile-jar-name**。最后,这段代码相当丑陋,我应该将其拆分为几个函数。

0
by

评论者:alexmiller

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

0
by

评论者:[email protected]

如果这个评论偏离了主题,请见谅。但原始例子对我来说有点困惑。也许它可以这样:

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

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

`

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

0
by

评论者:gsnewmark

@Alex Miller 您好!用类似Scala的方法(如果名字太长就对其进行哈希处理)的补丁会被考虑吗?由于这会破坏二进制兼容性,这个解决方案默认会被禁用,但可以通过使用新的编译器选项启用名称哈希。这种方法无疑会帮助我们的特定情况,但我不确定它是否足够有用和通用,可以被包括在编译器中,所以我还没有开始编写补丁。

0
by
_该评论由:alexmiller_发表_

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