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

我尝试使用 13 种模式进行 clojure.core.match,但在 Windows 下编译失败。我推测这是问题的根源。

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,所以我认为我们应该说这个错误也影响了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进行测试时得到了一个编译器异常java.lang.StackOverflowError。

0
by

评论者:gsnewmark

@Alex Miller 您好!如果补丁采用了类似于Scala的机制(在名称过长的情况下进行哈希),是否会被考虑?由于这会破坏二进制兼容性,因此这个修复方案默认会被禁用,但可以通过使用新的编译器选项来启用名称哈希。这个方法无疑会帮助我们解决这个问题,但我不确定它是否足够有用/通用,可以包含在编译器中,所以我还没有开始修改补丁。

0
by
_评论由:alexmiller_发布

不会引入任何破坏性更改。计划应该是在当前策略无效时切换第二个策略。
0
by
参考:https://clojure.atlassian.net/browse/CLJ-1852 (由 alex+import 报告)
...