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,编译:(未知源路径: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

尼科拉,CLJ-1746看起来是一个合理的建议,但它仍然没有解决这里的问题,原因与:exclude相同(请参阅我给亚历克斯的评论)

基本问题是当前的行怍会导致当库升级添加新变量时,用户代码会破裂,需要修改用户代码来修复/解决这个问题。我认为这是一个破坏性行为,或者至少是非常糟糕的设计。

特别是,我们被鼓励选择好的名字:我引用库编码标准(《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

Hi Nicola,我对人们使用显式的:refer / :require没有问题,并且我同意这是正常实践。清晰表达是好事,我通常也会这样做(除了在测试/演示代码中)。

然而,我们讨论的并非此案例:这个问题在用户(出于他们的正当原因)决定导入整个命名空间的情况下最为相关。这通常很方便(例如,REPL的使用),有时对特定目的很有价值(例如,测试)。

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

你可以说是他们的错,但Clojure目前确实应该支持这一点,所以我认为它应该平稳运行。

0 投票
by

评论人:alexmiller

我认为库/演化的论点是好的,而且我喜欢它减少了第三方库演化的破坏。

另一方面,如果我们删除这个错误,我们应该明确提出我们正在放弃什么,以便完全考虑这个问题。显然,我们至少放弃了在意外覆盖时出现的有用错误。还有其他影响吗?

我不期望我们在1.7版本中更改任何内容。

0 投票

评论作者:stu

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

一个反映命名空间的宏能否为此用法提供支持,而不需要更改核心?

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