请分享您的想法,参与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)

原因
IllegalStateException: 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 提出评论

嗨 Nicola,CLJ-1746 看起来像是一个合理的建议,但仍然没有解决这里的问题,原因和高危不允许重复冲突(参见我对 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 提出评论

你好,Nicola,我不介意人们使用显式的:refer / :require,并且我同意这是一种常规做法。明确性很重要,我一般也会这么做(除了在某些测试/演示代码中除外)。

但是我们谈论的不是这种情况:这个问题最相关的情况是,当用户(出于他们自己的合法原因)决定导入整个命名空间的情况。这种情况往往很方便(例如,在REPL使用时),有时对特定目的也有价值(例如,在测试中)。

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

你可以说是“这是他们的错”,但是现在Clojure本应支持这一点,因此我认为它应该正常工作。

0

评论者:alexmiller

我认为库/演化的争论是有道理的,我喜欢这一点,因为它减少了第三方库演化的破坏性。(我在clojure.core中也非常关注这个问题,其中它是自动引用的,其余则不那么强烈。)

另一方面,如果我们移除这个错误,我们应该明确我们放弃了什么,以便充分考虑。我们可能至少放弃了一个在误替换情况下发生的有用错误。还有其他影响吗?

我不希望我们在1.7中做出任何改变。

0
by

评论者:stu

将问题重新归类为功能请求,因为当前的行为是原始意图。

是否可以通过可反映命名空间的宏来实现这种用例,而无需更改核心?

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