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

原因
不合法状态异常: 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) 时的 (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',我看到了这种行为

用户=> (import '[try1.core :as c]) 警告:merge 已经在 try1.core 命名空间中引用了:#'clojure.core/merge,将被替换为:#'try1.core/merge 警告:* 已经在 try1.core 命名空间中引用了:#'clojure.core/*,将被替换为:#'try1.core/* nil 用户=> (import '[try1.core :as c] ) nil 用户=> (import '[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 做的事情与 (import ... :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
by

由 mikera 发布的评论

已关闭,因为我认为这更适合在相关问题中处理。

0
by

由 mikera 发布的评论

重新打开,因为CLJ-1578似乎不能解决这个具体问题,它只覆盖了clojure.core中的vars。

我仍希望解决这个问题,不仅仅是clojure.core中的namespace。

0
by
_评论由: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
by

评论由:bronsa添加

正如我已在CLJ-1578中评论的那样,我认为这不是一个错误,我认为这张票应该被拒绝。

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

0
by

评论由:bronsa添加

迈克,也许在 clojure-dev 邮件列表上提出这个问题能获取一些意见会更有意义?

0

由 mikera 发布的评论

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

我还是将其视为一个缺陷,因为我期望 :refer :all 能够正常工作。

无论如何,这个问题一直在我领域(数据科学 / 探索性统计学 / 数据管理)中破坏用户代码。使用 / 引用所有的能力对于设置便捷的探索性命名空间非常有用,所以我不会接受强制用户显式地要求每个使用的 var(如 Nicola 在 CLJ-1578 中所提出的)是一种实际的解决方案。

这也会在工作在 REPL 并重新加载命名空间时造成问题。

如果 Clojure 内核团队真的想要保持这种令人烦恼的行为,我们能否至少有一种在库级别关闭它的方法?也许是一些命名空间元数据,我可以将其添加到 clojure.core.matrix 命名空间中,以阻止这种情况触发?

0

评论由:bronsa添加

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

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

0

评论由: alexmiller

您可以使用 :exclude 来实现这一点

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

0

由 mikera 发布的评论

嘿,亚历克斯,当问题发生时,这是一种有效的修复方法,但并没有解决未来用户代码破坏的问题,除非用户准确预测将来会添加哪些符号到 "bar" 中。这再次似乎要求用户承担不合理负担。

我猜想,我所争论的是,如果用户在自己的命名空间中定义了变量,他们愿意替换任何之前使用过 / 全部引用过的命名空间中的同名变量。

如果用户真的担心意外覆盖,我会乐意看到一个 warn-on-replace 功能,它与 warn-on-reflection 大致相同。我之前在 CLJ-1257 中提出了类似的东西,甚至写了一个补丁,以这种方式解决了整个问题。我们能否在 1.7 中获得这个补丁或类似的东西?

...