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,编译:(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

评论者: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))
`

然后启动 REPL,使用 'lein repl',我看到这种行为

用户 > (require '[try1.core :as c]) 警告:merge 已在 try1.core 命名空间中引用: #'clojure.core/merge,将被替换为:#'try1.core/merge 警告:* 已在 try1.core 命名空间中引用: #'clojure.core/*,将被替换为:#'try1.core/* nil 用户 > (require '[try1.core :as c]) nil 用户 > (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

现在将其标记为 NR - 愿意看到它重新打开,并具有易于复制的测试用例。

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 命名空间中添加新的 var,用户代码中先前定义了具有相同名称的 var,编译器出错)这真的很令人烦恼。

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 中引用:#fbf/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)
原因
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
by

由 mikera 制作的评论

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

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

无论如何,这个问题仍然在我负责的领域(数据科学/探索性统计学/数据管理)中破坏用户代码。使用/引用所有的能力对于设置方便的探索工作命名空间非常有用,所以我不会接受强制用户显式要求每个使用的变量(如同在 CLJ-1578 中 Nicola 所建议的那样)作为一种实用的解决方案。

这也导致我在使用REPL和重新加载命名空间时遇到问题。

如果Clojure核心团队能够保持这种行为,我们能否至少有一种在库级别关闭它的方式?也许是一些命名空间元数据,我可以添加到clojure.core.matrix命名空间,以阻止这种情况发生?

0
by

评论者:bronsa

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

另外,要澄清的是,报告的问题在重新加载命名空间时不会出现,因为这个异常在重新定义发生时就被抛出了。

0
by

评论者:alexmiller

您可以使用:exclude来完成这个操作。

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

0
by

由 mikera 制作的评论

Hi Alex,这当问题发生时是一个修复方案,但它并没有解决未来用户代码破坏的问题,除非用户能准确地预见未来“bar”中可能添加哪些符号。这又似乎给用户带来了不合理的工作负担。

我猜想,我所主张的是,如果用户在自己的命名空间中定义一个变量,他们乐意替换他们在之前使用过的/require :all 中的任何同样命名的变量。

如果用户真的担心意外覆盖,我愿意接受 warn-on-replace,它与 warn-on-reflection 类似。我之前在 CLJ-1257 中提出过类似的想法,甚至编写了一个补丁,用这种方法解决了整个问题。我们能否在 1.7 中得到这个补丁或者类似的东西?

...