Clojure 2024 现状调查中分享您的观点!

欢迎!有关如何使用本站的一些更多信息,请参阅关于页面。

+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

尼古拉,CLJ-1746 看起来像是一个合理的建议,但仍然没有解决这个问题,原因与 :exclude 一样(见我对亚历克斯的评论)

基本问题是当前的行为会导致用户代码在库升级并添加新变量时中断,需要更改用户代码来修复/规避这个问题。我认为这是一个损坏的行为,或者至少是一个非常糟糕的设计。

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

Hi Nicola,我没有反对人们使用明确的:refer 或:require,并且我同意这是一种正常做法。明确性是好的,我通常也是这样做的(除了在测试/演示代码中)。

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

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

你可以说是“这是他们的错”,但Clojure目前应该支持这一点,因此我认为它应该以一种合理的方式工作。

0

评论者:alexmiller

我认为库/演进的论点是好的,我喜欢它减少了由于第三方库的演进而造成的破坏。(我对clojure.core本身,因为它是自动引用的,感觉非常强烈,否则则不太强烈。)

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

我不预期我们会为1.7版本进行任何改动。

0

评论由:stu

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

能否通过不要求对核心进行更改的方式,提供一个反映名字空间的宏以实现此用例?

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