2024年Clojure调查问卷!中分享你的想法。

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

+1 投票
Clojure

假设你有一个库在加载过程中会导致一些错误,如下所示

`
(ns broken-lib)

(} ; 这行将导致读取错误
`

然后,如果你require该库,即使发生了read错误,它也会被添加到{{loaded-libs}}中,这就使得之后的require成功执行而毫无声息。

user=> (contains? (loaded-libs) 'broken-lib) false user=> (require 'broken-lib) CompilerException java.lang.RuntimeException: Unmatched delimiter: }, compiling:(broken_lib.clj:3:3) user=> (contains? (loaded-libs) 'broken-lib) true user=> (require 'broken-lib) nil user=>

如果你还有一个需要损坏库的另一个命名空间(比如这里的{{broken-lib.core}}),情况变得更糟

(ns broken-lib.core (:require [broken-lib :as lib]))

虽然你会得到依赖于命名空间首次加载时的实际错误,但之后你将会发现每次尝试重新加载它都会触发一个错误的编译器异常。即使你实际情况中修复了导致原始错误的代码,这个问题依然会存在。

`
user=> (require 'broken-lib.core)

CompilerException java.lang.RuntimeException: Unmatched delimiter: }, compiling:(broken_lib.clj:3:3)

user=> (require 'broken-lib.core :reload)
CompilerException java.lang.Exception: namespace 'broken-lib' not found, compiling:(broken_lib/core.clj:1:1)

user=> (require 'broken-lib.core :reload) ;; 修复broken-lib中的bug后的重新加载

CompilerException java.lang.Exception: namespace 'broken-lib' not found, compiling:(broken_lib/core.clj:1:1)
user=>
`

原因
CLJ-1116的补丁使{{ns}}宏在加载过程中出现错误时,盲目地将正在定义的库添加到{{loaded-libs}}中。

方法
修改{{clojure.core/load-lib}},以便在出错时将其从{{loaded-libs}}中删除。

7 答案

0 投票

由:alexmiller发表评论

这个补丁似乎与问题的原因有些脱节 - 有没有某种方式可以阻止一开始就将库添加到 loaded-libs 中的呢?

0 投票

评论者:sohta

为了这样做,我认为我们需要回滚 CLJ-1116。

0 投票

由:alexmiller发表评论

我认为这个解决方案不太理想,所以将其移至不完整状态。

0 投票

评论者:sohta

您对这个问题的解决方案有何期待?

为了避免一开始就将库添加到 loaded-libs 中,我认为 ns 宏需要知道它从哪里被使用。当用于 CLJ-1116 的 REPL 时,它应该立即添加 ns,而当在文件中使用时,它应该在完成整个文件的错误无误加载后延迟添加 ns。

0 投票

评论者:gshayban

附加了与 Shogo Ohta 原始方法类似的方法。考虑到 ns 现在的工作方式,我认为这种方法是可行的。

为了支持在 REPL 中动态创建 ns,CLJ-1116 在 ns 宏中写入 loaded-libs,同时也在 load-lib 和 load-libs 中做了一些逻辑,这使得它们不再必要。这一系列补丁清除了加载失败时的副作用,并清理了一些死条件。

新行为:给定需要 #{B, C} 的 ns A,如果 B 加载但 C 不加载,则只有 B 将写入 loaded-libs,A 和 C 将被撤销。这改善了加载体验并修复了所有令人讨厌的票证描述中的行为。

注意:'require' 补丁意味着
如果一个库在 ns :require 或 :use 中指定,那么第一次加载该库必须导致一个与库名称完全对应的新建 ns。(当直接调用 load 时,从来就没有过这样的限制,但只有通过 ns 调用)我在测试套件中意外地发现了一个带有下划线的累赘库,加载后的代码产生了一个包含短横线的命名空间。(也许 c.c.specs 应该为库指定比 'simple-symbol?' 更严格的规范?)

提交被分开,附有简短的解释性注释。

0 投票

由:alexmiller发表评论

注意 - CLJ-2026 可能由于任何针对这个更广泛问题的修复而变得无关紧要,然后可以被移除。

0 投票
参考资料:https://clojure.atlassian.net/browse/CLJ-1406(由sohta报告)
...