请在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
"This definition of merge replaces clojure.core/merge"
[x y]
(- x y))

(defn
[x y]
(
x y))
`

然后使用'lein repl'启动REPL,我看到这种行为

用户=> (require '[try1.core :as c]) 警告:merge 已经引用:#'{clojure.core/merge} 在命名空间:try1.core,将被替换为:#'{try1.core/merge} 警告:* 已经引用:#'{clojure.core/*} 在命名空间:try1.core,将被替换为:#'{try1.core/*} nil 用户=> (require '[try1.core :as c] ) nil 用户=> (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 (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 中的 vars,因此将其重新打开。

我还是希望这一问题能对所有命名空间进行修复,而不仅仅是 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 一样,我认为这并不是一个错误,我认为应该拒绝这个工单。

覆盖非 clojure.core 的 vars 从 1.2 版本开始(至少)都始终会抛出异常。

0

评论者:bronsa

Mike,也许在 clojure-dev ml 中提出这个问题以获取一些意见是有意义的?

0
by

评论者:mikera

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

我仍然将其视为缺陷,因为我期望:refer :all 能够正常工作。

无论如何,这个问题仍然会破坏我领域的用户代码(数据科学/探索性统计/数据管理)。使用/引用所有功能对于设置方便的命名空间进行探索性工作非常有用,因此我不接受强制用户显式地要求每个使用的var(正如Nicola在CLJ-1578中建议的那样)是一种可行的解决方案。

这也导致我在REPL中使用重载命名空间时遇到了问题。

如果Clojure核心团队真的想保持这种令人讨厌的行为,我们至少可以在库级别关闭它?也许是一些命名空间元数据,我可以将其添加到clojure.core.matrix命名空间以防止该问题被触发?

0
by

评论者:bronsa

Mike,这只是我个人的看法,我不是核心团队的一员,也不代表他们,这就是我建议你在clojure-dev ml上写的原因。

此外,为了澄清,您报告的这个问题在重载数命名空间时不会出现,因为异常会在重新定义时立即抛出。

0
by

评论为:alexmiller

您可以使用 :exclude 来解决这个问题

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

0
by

评论者:mikera

Hi Alex,当出现问题时,这可以作为修复方案,但不能解决未来用户代码中断的问题,除非用户准确预测未来可能添加到"bar"中的符号。这又似乎给用户带来了不合理的要求。

我想我争论的是,如果用户在自己的命名空间中定义了一个var,他们愿意替换任何先前使用'd / refer-all'd的命名空间中相同名称的var。

如果用户真正担心意外替换事物,我将很高兴接受一个 warn-on-replace,其功能类似于 warn-on-reflection。我在CLJ-1257中提出过类似的建议,甚至还编写了一个补丁,用这种方法解决了整个问题。我们能否在1.7中得到这个补丁或类似的解决方案?

...