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 中的 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

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

为了防止库一开始就被添加到加载的库中,我认为ns宏需要知道其使用位置。对于CLJ-1116,它应该立即在REPL中使用ns,而文件内部使用时应推迟添加ns直到完成无错误地加载整个文件。

0

评论者:gshayban

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

为了支持REPL中的动态ns创建,CLJ-1116在ns宏内写入了加载的库,同时简化了load-lib和load-libs中的某些逻辑。这一套补丁取消了加载失败时的副作用,并清理了一些死代码。

新行为:给定需要#{B, C}的ns A,如果B加载但C没有,则只会在加载的库中写入B,并且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报告)
...