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

欢迎!请访问 关于 页面以获取更多关于如何使用本站的信息。

+1
Clojure

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

`
(ns broken-lib)

(} ; 这一行将引发一个读取错误
`

然后,即使发生了读取错误,该库也将会被添加到 {{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 中的错误后重新加载

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 发表的评论:

您对这个问题的解决方案有什么期望?

为了从一开始就防止lib被添加到loaded-libs中,我认为ns宏需要知道它从哪里使用。当在REPL中使用时,它应该立即为CLJ-1116添加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
by
参考: https://clojure.atlassian.net/browse/CLJ-1406(由sohta报告)
...