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)
CompilerException java.lang.IllegalStateException: a 已经在命名空间 bar 中引用: #'foo/a,编译:(NO_SOURCE_PATH:1:1)
=> *clojure-version*
{:major 1, :minor 7, :incremental 0, :qualifier "RC1"}

堆栈跟踪

CompilerException 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,那么他们愿意替换他们之前使用过的/引用-all过的任何命名空间中具有相同名称的var。

如果用户确实担心意外覆盖,我愿意接受一个,它的作用与类似。我之前在CLJ-1257中提出了这个想法,甚至写了一个补丁,用这种方式解决了整个问题。我们能否在1.7中获取这个补丁或类似的东西?

...