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 定义的 merge 替换 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(NoReally)- 我乐意看到它重新打开,以便重现测试用例。

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 已经在命名空间 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 变量自古以来(至少从 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

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

我想,我争辩的是,如果一个用户在自己的命名空间中定义了一个变量,那么他们愿意用任何之前已使用过/refer-all'd的命名空间中相同名称的变量来替换它。

如果用户真的担心意外覆盖这些内容,我乐于看到实现类似 warn-on-reflectionwarn-on-replace 功能。我之前在 CLJ-1257 中提出了类似的想法,甚至已经编写了一个补丁,以这种方式解决了整个问题。1.7 版本能否加入这个补丁或类似的功能?

...