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 已经在命名空间 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

评论者:alexmiller

您能为此情况创建一个更好、不依赖于 core.matrix 的可重复测试用例吗?同时,请包括当 (pst **e) 发生时的相关内容。

0

评论者:jafingerhut

我已经尝试了我想象中最小的 Leiningen 项目来引发有关重定义的警告,看看是否可以触发异常。'lein new try1' 创建基本的骨架项目,然后编辑 src/try1/core.clj 以包含以下函数定义:

`
(defn merge
"此 merge 的定义替换了 clojure.core/merge"
[x y]
(- x y))

(defn
[x y]
(
x y))
`

然后通过 'lein repl' 启动一个 REPL,我看到了这种行为

user=> (require '[try1.core :as c]) 警告:合并已引用:#'clojure.core/merge 在命名空间:try1.core,正在被替换为:#'try1.core/merge 警告:* 已引用:#'clojure.core/* 在命名空间:try1.core,正在被替换为:#'try1.core/* nil user=> (require '[try1.core :as c] ) nil user=> (require '[try1.core :as c] :reload) 警告:合并已引用:#'clojure.core/merge 在命名空间:try1.core,正在被替换为:#'try1.core/merge 警告:* 已引用:#'clojure.core/* 在命名空间:try1.core,正在被替换为:#'try1.core/* nil

这看起来像是我预期的行为,我没有看到Mike所报告的异常。

这看起来好像在Counterclockwise中使用Ctrl+Alt+L所做的与(require ... :reload)不同,或者Mike的命名空间除了重新定义clojure.core中名称的其它地方也导致了问题。

0

评论者:alexmiller

目前将其标记为NR( noting reproducible )- 很乐意看到它重新打开,并提供一个易于重复的测试用例。

0

评论者:mikera

重现方法

(ns op)
(defn (link: a b) (clojure.core/ a b)) ;; 给出警告
(ns use-op (:require (link: op :refer :all))) ;; 给出警告
(ns use-op (:require (link: op :refer :all))) ;; 给出错误!

我认为Counterclockwise使用CTRL-Alt+L简单地再次加载命名空间,这导致ns表达式被重新执行。

文档字符串表明可以多次使用ns("将命名空间设置为通过name命名的命名空间(未评估),如果需要则创建它"),因此我当然期望多次调用ns是空操作。

0

评论者:alexmiller

在CLJ-1578中重复。

0

评论者:mikera

这仍然在影响我,并与最新版本的core.matrix产生冲突。我不知道这是否是一个后退,但它在1.7.0-RC1中确实发生了。

我们能否为1.7获得一个修复?由于这个问题导致代码失败,并需要大规模重构用户代码,这真的非常令人烦恼(我的用例是向clojure.core.matrix命名空间添加一个新变量,用户代码中使用具有相同名称的变量的编译器错误)。

0

评论者:mikera

关闭原因是我们认为这个问题最好在相关的问题中进行处理。

0

评论者:mikera

重新打开是因为CLJ-1578显然没有解决这个问题,它只涵盖了clojure.core中的变量。

我希望修复所有的命名空间,而不仅仅是clojure.core。

0
评论者:mikera

重放

=> (ns foo)
nil
=> (def a 1)
#'foo/a
=> (ns bar (:require [foo :refer :all]))
nil
=> (def a 2)
编译器异常 java.lang.IllegalStateException: a 已经在namespace: bar中引用: #'foo/a,编译位置:(无源文件路径:1:1)
=> *clojure-version*
{:major 1, :minor 7, :incremental 0, :qualifier "RC1"}

堆栈跟踪

编译器异常 java.lang.RuntimeException:无法在当前环境中解析符号:pst,编译位置:(无源文件路径:1:1)
    clojure.lang.Compiler.analyze (Compiler.java:6543)
    clojure.lang.Compiler.analyze (Compiler.java:6485)
    clojure.lang.Compiler$InvokeExpr.parse (Compiler.java:3737)
    clojure.lang.Compiler.analyzeSeq (Compiler.java:6735)
    clojure.lang.Compiler.analyze (Compiler.java:6524)
    clojure.lang.Compiler.analyze (Compiler.java:6485)
    clojure.lang.Compiler$BodyExpr$Parser.parse (Compiler.java:5861)
    clojure.lang.Compiler$FnMethod.parse (Compiler.java:5296)
    clojure.lang.Compiler$FnExpr.parse (Compiler.java:3925)
    clojure.lang.Compiler.analyzeSeq (Compiler.java:6731)
    clojure.lang.Compiler.analyze (Compiler.java:6524)
    clojure.lang.Compiler.eval (Compiler.java:6789)
原因
RuntimeException 无法在当前环境中解析符号:pst
    clojure.lang.Util.runtimeException (Util.java:221)
    clojure.lang.Compiler.resolveIn (Compiler.java:7029)
    clojure.lang.Compiler.resolve (Compiler.java:6973)
    clojure.lang.Compiler.analyzeSymbol (Compiler.java:6934)
    clojure.lang.Compiler.analyze (Compiler.java:6506)
    clojure.lang.Compiler.analyze (Compiler.java:6485)

0

评论者:bronsa

正如我已经在CLJ-1578中评论的那样,我认为这不是一个错误,并且我认为应该拒绝这个工单。

自1.2版以来(至少),覆盖非clojure.core变量总是会导致异常。

0

评论者:bronsa

Mike,你或许应该在 clojure-dev ml 上提出这个问题,看看别人的意见如何?

0

评论者:mikera

如果你更喜欢,可以将其重新归类为一个功能请求。

我仍然认为这是一个缺陷,因为我期待 :refer :all 能正常工作。

无论如何,这个问题一直破坏我在数据科学/探索性统计学和数据管理方面的用户代码。使用/引用所有功能对设置便利的命名空间进行探索性工作非常有用,所以我不会接受强迫用户明确要求每个使用的var(如Nicola 在 CLJ-1578 中建议的那样)是一个实用的解决方案。

这也在我使用REPL和重新加载命名空间时引起了一些问题。

如果Clojure核心团队真的想要保持这种令人讨厌的行为,我们至少能在库级别上有一种关闭它的方法吗?也许可以在clojure.core.matrix命名空间中添加一些命名空间元数据来阻止这种情况发生?

0

评论者:bronsa

Mike,这只是我个人的观点,我不是核心团队的一员,也不代表他们,这就是我建议你写 clojure-dev ml 的原因。

此外,为了澄清,你报告的这个问题在重新加载命名空间时不会表现出来,因为异常会在重新定义时立即抛出。

0

评论者:alexmiller

你可以使用 :exclude 来解决这个问题

(ns bar (:require [foo :refer :all :exclude (a)]))

0

评论者:mikera

嗨Alex,当问题发生时,这确实可以作为解决方案,但它不会解决未来用户代码损坏的问题,除非用户准确预测在未来可能会添加到 "bar" 中的符号。这显然给用户带来了不合理的要求。

我可能主张的是,如果用户在自己的命名空间中定义了一个var,那么他们很乐意替换他们之前使用过的/引用的所有命名空间中具有相同名称的var。

如果用户真心担心意外覆盖问题,我会对替换时警告(warn-on-replace)感到满意,这种警告功能与反射时警告(warn-on-reflection)类似。我之前在CLJ-1257中提出了类似的想法,甚至为此编写了一个补丁,以这种方式解决了整个问题。我们能否在1.7版本中得到那个补丁或者类似的实现呢?

...