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 宏需要知道其使用位置。当用于 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应该比“简洁符号?”为库指定更严格的规范)

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

0

评论由:alexmiller 提出

注意 - 如果对更广泛的问题进行任何修复,CLJ-2026可能变得不再相关,并可以从中移除。

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