2024年 Clojure 状态调查!中分享您的观点。

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

+1
错误

`
=> (ns foo)
nil
=> (def a 1)

'foo/a

=> (ns bar (:require [foo :refer :all]))
nil
=> (def a 2)
编译器异常 java.lang.IllegalStateException: a 已经指向: #'foo/a 在命名空间: bar, 编译:(NO_SOURCE_PATH:4:1)

clojure.lang.Compiler.analyzeSeq (Compiler.java:6745)
clojure.lang.Compiler.analyze (Compiler.java:6529)
clojure.lang.Compiler.analyze (Compiler.java:6490)
clojure.lang.Compiler.eval (Compiler.java:6801)
clojure.lang.Compiler.eval (Compiler.java:6760)
clojure.core/eval (core.clj:3079)
clojure.main/repl/read-eval-print--7095/fn--7098 (main.clj:240)
clojure.main/repl/read-eval-print--7095 (main.clj:240)
clojure.main/repl/fn--7104 (main.clj:258)
clojure.main/repl (main.clj:258)
clojure.main/repl-opt (main.clj:324)
clojure.main/main (main.clj:422)

原因:
非法状态异常 a 已经指向: #'foo/a 在命名空间: bar

clojure.lang.Namespace.warnOrFailOnReplace (Namespace.java:88)
clojure.lang.Namespace.intern (Namespace.java:72)
clojure.lang.Compiler$DefExpr$Parser.parse (Compiler.java:534)
clojure.lang.Compiler.analyzeSeq (Compiler.java:6738)
clojure.lang.Compiler.analyze (Compiler.java:6529)

`

我原本预期(最坏的情况)会看到与最初命名空间加载时类似的警告,而不是在这里抛出异常。

22 答案

0

评论者:bronsa

CLJ-1746是相关的,并且我比CLJ-1257更喜欢该提议。

0

评论者:mikera

尼可拉,CLJ-1746看起来像是一个合理的建议,但仍然没有解决此处的问题,原因与:exclude 的问题相同(见我对 Alex 的评论)

基本问题是,当前的行为会在库升级以添加新变量时导致用户代码中断,需要修改用户代码以修复/规避此问题。我认为这是不正确的行为,或者至少是很差的设计。

这尤其是因为我们被鼓励选择好的名字:我引用库编码标准(http://dev.clojure.org/display/community/Library Coding Standards)

使用良好的名字,并且不要害怕与其他命名空间中的名字冲突。这就是灵活的命名空间支持所在的原因。

当用户代码不断出错时,这并不灵活。

0

评论者:bronsa

从同一页面的下一行开始。
明确且极简地处理对其他包的依赖。(在1.4+中优先使用 :require :refer,在1.0-1.3中使用 :use :only)。

如果用户不小心导入整个包,我认为这是他们的错。自Clojure 1.3以来,普遍共识是使用 :use/:refer :all 不是一个好主意,人们已经逐渐远离这种方式,更愿意使用 :require :refer 或 :require :as。

仍然使用 :use/:refer :all 的人数很少,这主要是因为为了向后兼容或进行测试(我自己出于后者的原因在 tools.reader 中这样做)。

我真的不认为这像你说的那样是一个不好的设计选择,我认为社区的大多数人都会同意,当前的行为和使用 :require :refer/require :as 替代 :use/:refer :all 的趋势比有害更多。

0

评论者:mikera

尼古拉,我没有任何问题,使用明确的 :refer / :require,我同意这是正常做法。明确化很好,我通常也会这样做(除了测试/演示代码)。

但是,我们讨论的不是这种情况:这个问题最主要的相关情况是,用户(出于他们自己的合法权益)决定导入整个命名空间。这通常是方便的(例如REPL使用),有时是为了特定目的而宝贵的(例如测试)。

我主要从库作者的视角关注这一点:我希望用户能够以最方便的方式使用库(这可能包括导入所有变量),并且我不希望在我进行新版本发布时用户代码随机出错。请注意,这也意味着我无法控制用户代码,所以任何涉及明确要求、排除或其他手动解决方案的方法都不是实用的解决方案。

你可以这么说:“这是他们的错”,但 Clojure 目前应该支持这种情况,我认为它应该按正常工作。

0

评论者:alexmiller

我认为库/进化的论点是好的,我喜欢它减少了由第三方库进化引起的破坏。在这方面我很关注 clojure.core 本身(它是自动引用的),否则则不那么关注。

另一方面,如果我们删除这个错误,我们应该明确我们正在牺牲什么,以便充分考虑到它。我们可能至少在意外覆盖的情况下牺牲了一个有用的错误。还有其他影响吗?

我不期待我们在1.7版本中进行任何更改。

0

评论者:stu

重新分类为功能请求,因为当前行为是原始意图。

一个反映命名空间的宏是否能够在不更改核心的情况下提供这种用例?

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