请分享您的看法,参加2024年 Clojure 状态调查!

欢迎!请查阅关于页面获取更多关于该功能的信息。

+1 点赞
错误

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

'foo/a

=> (ns bar (:require [foo :refer :all]))
nil
=> (def a 2)
抛出CompilerException java.lang.IllegalStateException: a 已经在命名空间 bar 中引用了: #'foo/a,编译文件:(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 已经在命名空间 bar 中引用了: #'foo/a

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 同样(参见我给亚历克斯的评论)

根本问题是当前行为会在库升级以添加新变量时导致用户代码出错,并且需要修改用户代码来修复或工作ueva

特别是在我们被鼓励选择好名字时(我引用库编码标准(http://dev.clojure.org/display/community/Library Coding Standards):

"使用好名字,不要害怕与其他命名空间的名称冲突,这就是灵活的命名空间支持的用途."

当用户代码总是出错时,这并不太灵活......

0 点赞
by

评论由: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 点赞
by

评论由:mikera 提出

尼古拉,我没有问题人们使用明确的 :refer / :require,我也同意这是正常实践。明确度是好的,我通常也是这样做的(除测试/演示代码外)。

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

我个人主要从库作者的角度关心这件事:我希望用户能够以最方便的方式使用库(这可能会包括导入所有变量),并且我不希望我的新版本发布时用户代码随机崩溃。请注意,这也意味着我无法控制用户代码,所以任何涉及显式 requires、排除或其他手动解决方案的解决方案都不是实际的解决方案。

你可以说是他们的错,但Clojure目前应该支持它,所以我认为它应该正常工作。

0 点赞
by

评论者:alexmiller

我认为库/发展论点是很好的,我也喜欢它因第三方库的发展而减少了破坏性。(我在clojure.core本身中对此感觉非常强烈,因为它是自动引用的,在其他情况下则不那么强烈。)

另一方面,如果我们移除这个错误,我们应该明确我们是在放弃什么,以便充分考虑。我们可以推测,我们至少是在处理意外覆盖时发生的有用错误中放弃了一些东西。是否有其他影响?

我不期望在1.7版本中做出任何修改。

0 点赞
by

评论者:stu

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

一个表示命名空间的宏是否可以在不修改核心的情况下提供这种用例?

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