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: File name too long}} 异常。

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

有没有进展?这个工单被标记为“关键”。
我已经为其打了标签。它不在我们1.12的列表中,但我在1.13的列表中提到了它。

10 个答案

0
by

评论区由 martinraison 建立

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

0
by

评论区由 panewman 建立

我在 Windows 下使用 clojure.core.match 和 13 种模式时,编译失败了。我猜想这是根本原因。

0
by

_评论区由 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
by

评论区由 alexvong1995 建立

你好,

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

我认为解决这个问题的方法之一是提供一个选项,将类文件打包成 jar,使用较短的文件名,这样类名就可以保持不变(zip 文件名可以任意长,对吗?)。你认为呢?

顺便说一下,我正在使用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得到了CompilerException java.lang.StackOverflowError。

0
by

评论者:gsnewmark

@Alex Miller 你好!是否有类似Scala的解决方案(如果名称太长则对名称进行散列)会被考虑?这种解决方案会打破二进制兼容性,因此这个解决方案将默认禁用,但可以通过新的编译器选项启用名称散列。这种方法肯定有助于我们特定的案例,但我不确定它是否足够有用和通用,可以包含在编译器中,所以我还没有开始修补它。

0
_评论由:alexmiller_ 发布

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