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

欢迎!请查看 关于 页面以获取更多关于此功能的信息。

+1
Clojure

假设您有一个在加载过程中引发一些错误的库,如下所示

`
(ns broken-lib)

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

然后,如果您 {{require}} 该库,它将在读取器错误后添加到 {{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

你期望如何解决这个问题?

为了从一开始就防止库被添加到 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
by

由 alexmiller 发表的评论

注意 - 如果对更广泛的问题进行修复,则 CLJ-2026 可能变得不相关,并可将其移除。

0
by
...