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 已经在命名空间 bar 中引用#'foo/a,编译:(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 已经在命名空间 bar 中引用#'foo/a

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已经引用:#'clojure.core/merge,命名空间:try1.core,将被替换为:#'try1.core/merge 警告:*已经引用:#'clojure.core/*,命名空间:try1.core,将被替换为:#'try1.core/* nil user=> (require '[try1.core :as c]) nil user=> (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 (a b) (clojure.core/ a b))) ;; 提示警告
(ns use-op (:require (op :refer :all))) ;; 提示警告
(ns use-op (:require (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 已经在命名空间 bar 中引用:#'foo/a,编译于:(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中提到的,我认为这不是一个bug,我建议拒绝这个工单。

覆盖非clojure.core变量始终(至少从1.2版本开始)会导致抛出异常。

0

由:bronsa 发表的评论

Mike,也许将这个问题提到clojure-dev ml中,以获取一些意见,是个不错的办法?

0

评论者:mikera

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

我仍视其为缺陷,因为我期望 :refer :all 可以正常工作。

无论如何,这个问题不断破坏我在数据科学/探索性统计/数据管理区域中的用户代码。使用/引用所有功能对于设置方便的探索性工作命名空间非常有用,因此我不同意尼古拉在 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”会增加什么符号。这又似乎给用户带来了不合理的要求。

我 guessed 所争论的是,如果用户定义了自己命名空间中的变量,那么他们愿意替换任何之前使用'd/refer-all'd的命名空间中具有相同名称的变量。

如果用户真正担心意外覆盖,我乐意看到一个 warn-on-replace,它可以做到和 warn-on-reflection 类似的事情。我早就提出了类似的方案,甚至写了一个补丁,以这种方式解决了整个问题。我们能否将这个补丁或类似的东西放入 1.7 中?

...