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

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 (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中已评论的,我认为这不是一个错误,我认为这张票应该被拒绝。

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

0 投票

评论者:bronsa

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

0 投票

由 mikera 发布的评论

如果您喜欢,请将其重新分类为功能请求。

我仍然认为这是一个缺陷,因为我期望:refer :all能正常工作。

无论如何,这个问题总是破坏我在该区域(数据科学/探索统计学/数据管理)的用户代码。使用/引用所有对于为探索性工作设置方便的命名空间非常有用,所以我不能接受强制用户明确要求每个使用的var(正如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,那么他们高兴地替换在先前使用/引用-all'd过的任何命名空间中具有相同名称的var。

如果用户真正担心意外替换,我将接受一个warn-on-replace,它与warn-on-reflection类似。我以前在CLJ-1257中提出过类似的东西,甚至编写了一个补丁,以这种方式解决了整个问题。我们能在1.7中得到这个补丁或类似的东西吗?

...