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

然后使用 '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 设置为通过名称指定的命名空间(未评估),如需要则创建)所以我会确实期望多次调用 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 中引用了:#'foo/a,在(NOSOURCEPATH:1:1)编译
=> *clojure-version*
{:major 1, :minor 7, :incremental 0, :qualifier "RC1"}

堆栈跟踪

编译器异常:java.lang.RuntimeException:在这个上下文中无法解析符号:pst,在(NOSOURCEPATH: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中,我就已经评论过这个问题,我认为这不是一个错误,并认为应该拒绝这个工单。

自1.2版本(至少)以来,覆盖非clojure.core变量一直会抛出异常。

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 提出

亚历克斯,这确实在发生问题时解决了问题,但它并没有解决未来用户代码破损的问题,除非用户能够准确预测未来可能会添加到“bar”中的符号。这再次似乎是对用户的 extremes 加载。

我想我争论的是,如果用户在自己的命名空间中定义了一个变量,那么他们宁愿替换他们之前使用过或参照过/引用过的任何命名空间中的具有相似名称的变量。

如果用户真正担心意外地覆盖东西,我将满足于一个 warn-on-replace,它类似于一 样的警告On-reflection。我之前在CLJ-1257中提出过类似的观点,甚至编写了一个补丁来以这种方式解决整个问题。我们能否在1.7中获得这个补丁或类似的东西?

...