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,我看到这种行为

用户=> (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) 做的事情不同,或者除了重定义 clojure.core 中的名称外,Mike 的命名空间还有一些不同之处导致了这个问题。

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 ml写了。

此外,为了澄清,在重新加载命名空间时,这个问题无法出现,因为异常会在重新定义发生时抛出。

0

由:alexmiller 发布的评论

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

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

0

由 mikera 创建的注释

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

我猜想,我争论的是默认假设,如果用户在自己的命名空间中定义了一个var,他们愿意替换任何先前使用过的/ refer-all'd命名空间中具有类似名称的var。

如果用户确实担心意外替换,我将很高兴有一个 warn-on-replace,它的工作方式类似于 warn-on-reflection。我曾在CLJ-1257中提出过类似的建议,甚至编写了一个补丁以这种方式解决整个问题。我们能否在1.7中获取这个补丁或类似的东西?

...