2024 年 Clojure 状态调查 中分享您的想法!

欢迎!请参阅 关于 页面以获取更多关于如何使用本站的信息。

+1
错误

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

'foo/a

=> (ns bar (:require [foo :refer :all]))
nil
=> (def a 2)
编译器异常 java.lang.IllegalStateException: 在命名空间 bar 中,变量 a 已经指向: #'foo/a

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)

原因如下
非法状态异常:在命名空间 bar 中,变量 a 已经指向: #'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]) 警告: merge 已经在命名空间 try1.core 中引用了: #'clojure.core/merge,正在被替换为: #'try1.core/merge 警告: * 已经在命名空间 try1.core 中引用了: #'clojure.core/*,正在被替换为: #'try1.core/* nil user=> (require '[try1.core :as c]) nil user=> (require '[try1.core :as c] :reload) 警告: merge 已经在命名空间 try1.core 中引用了: #'clojure.core/merge,正在被替换为: #'try1.core/merge 警告: * 已经在命名空间 try1.core 中引用了: #'clojure.core/*,正在被替换为: #'try1.core/* nil

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

似乎在 Counterclockwise 中 Ctrl+Alt+L 做的事情与 (require ... :reload) 不同,或者Mike的命名空间中除了在 clojure.core 中重定义名称之外,还存在某种不同导致问题发生。

0

评论来自:alexmiller

目前将其标记为未修复 - 如果能以简单可重复的测试用例重新打开它,我将很高兴。

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 可以多次使用("将 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 已经在命名空间 bar 中引用:`'foo/a`,正在编译:(NO_SOURCE_PATH:1:1)
=> *clojure-version*
{:major 1, :minor 7, :incremental 0, :qualifier "RC1"}

堆栈跟踪

编译器异常 java.lang.RuntimeException:无法在当前上下文中解析符号:pst,正在编译:(NO_SOURCE_PATH: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)
原因如下
运行时异常 无法在当前上下文中解析符号: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中所评论的那样,我认为这不是一个错误,并认为这个工单应该被拒绝。

覆盖非clojure.core变量始终(至少从1.2版本开始)会导致抛出异常。

0

评论者:bronsa

Mike,也许在clojure-dev ml上提出这个问题以听取一些意见是有意义的?

0

由 mikera 发布的评论

如果您愿意,可以重新将其归类为一个功能请求。

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

无论如何,这个问题总是会导致我所在领域(数据科学/探索性统计/数据管理)的用户代码出现错误。使用/引用所有功能对于建立方便的命名空间进行探索性工作非常有用,因此我不接受强制用户明确启用每个变量的做法(正如在 CLJ-1578 中 Nicola 建议)是一个实际的解决方案。

这也在我用 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" 的符号。这再次给用户带来了不合理的要求。

我想,我争论的是,如果用户在自己的命名空间中定义了一个变量,他们应该默认乐于替换先前通过 refer-all 使用的任何命名空间中相似名称的变量。

如果用户真的担心意外覆盖,我愿意使用一个类似 warn-on-reflectionwarn-on-replace,它做得类似于 warn-on-reflection。我之前在 CLJ-1257 中提出过类似的东西,甚至写过一段补丁,用这种方式解决了整个问题。我们能在 1.7 中得到这个补丁或类似的东西吗?

...