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

欢迎!有关此网站的更多信息,请参阅 关于 页面。

+1
错误

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

'foo/a

=> (ns bar (:require [foo :refer :all]))
nil
=> (def a 2)
编译器错误:java.lang IllegalStatProvinceException: 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)

原因
IllegalStatProvinceException 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))
`

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

用户=> (require '[try1.core :as c]) 警告:merge 已经指向:#'(clojure.core/merge) 在命名空间:try1.core,将被替换为:#'(try1.core/merge) 警告:* 已经指向:#'(clojure.core/*) 在命名空间:try1.core,将被替换为:#'(try1.core/*) nil 用户=> (require '[try1.core :as c]) nil 用户=> (require '[try1.core :as c] :reload) 警告:merge 已经指向:#'(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(待定)- 如果有一个简单的可重复测试用例,我很乐意看到它重新开放。

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 simply又用CTRL-Alt+L重新加载了命名空间,这导致了ns形式的重新执行。

文档字符串暗示ns可以被多次使用(“设置ns为由name命名(未评估)的命名空间,需要时创建”),所以我会期望multiple invocations of 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 已经引用:#'foo/a 在命名空间:bar,编译:(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 中评论的那样,我认为这不是一个错误,我认为这个工单应该被拒绝。

重写非 clojure.core 变量自 1.2 版本以来(至少)一直会导致抛出异常。

0

评论者:bronsa

Mike,也许将这个问题提交到clojure-dev ml以获取一些意见是有意义的?

0

评论由:mikera

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

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

无论如何,这个问题会破坏我领域(数据科学/探索性统计/数据管理)的用户代码。使用/引用所有对于设置便利的命名空间进行探索性工作非常有用,所以我不能接受强制用户显式要求每个使用的变量(如 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

Hi Alex,当问题发生时,这是一个解决问题的修复方法,但这不解决未来用户代码破坏的问题,除非用户能够准确预测未来可能会添加哪些符号到"bar"。这又似乎给用户带来了不合理的工作负担。

我想争论的是,我觉得用户在自己的命名空间中定义变量时,如果他们开心,愿意替换掉任何之前使用/参考过的命名空间中相似名称的变量。

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

...