请在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

评论由: alexmiller 撰写

您能对这个测试用例进行更好的重现,使得它不依赖于core.matrix吗?同时,请包括发生时的(pst **e)。

0

评论由:jafingerhut 撰写

我尝试了一个最小的Leiningen项目来引发关于重定义的警告,看看是否能引发异常。执行命令'lein new try1'创建骨架项目,然后编辑src/try1/core.clj以包含以下函数定义...

`
(defn 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 撰写

暂时将其标记为 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 命名空间中添加新的变量,用户代码中先前定义的变量相同的名称出现编译器错误)真是太令人烦恼了。

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 邮件列表写邮件。

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

0

评论由: alexmiller 撰写

你可以使用 :exclude 来做这个

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

0

由 mikera 发表的评论:

亚历克斯,这确实在问题发生时是一个修复方案,但它并没有解决未来用户代码损坏的问题,除非用户准确预测出未来可能添加到 "bar" 中的符号。这又似乎是用户的不合理负担。

我猜我在争论的是,如果用户在其自己的命名空间中定义了一个变量,他们愿意替换他们之前使用/引用的所有命名空间中具有相同名称的变量。

如果用户真正担心意外替换,我将很高兴看到 warn-on-replace,它类似于 warn-on-reflection。我在 CLJ-1257 中提出过类似的想法,并写了一个补丁,以这种方式解决了整个问题。我们能否在 1.7 中得到这个补丁或者是类似的东西?

...