2024 Clojure 状态调查! 中分享您的想法。

欢迎!请参阅 关于 页面以了解更多有关此功能的信息。

0
Clojure

以下代码失败(在 1.6 和最新的 1.7-alpha4 中都如此)

`
user=> (ns foo)
nil
foo=> (def inc inc)
WARNING: inc 已经在命名空间 foo 中引用: #'clojure.core/inc,正在进行替换为: #'foo/inc

'foo/inc

;; 注意此刻 inc 是未绑定的,这导致以下异常
foo=> inc

foo=> (ns bar)
nil
bar=> (require ['foo :refer ['inc]])
WARNING: inc 已经在命名空间 bar 中引用:#'clojure.core/inc,正在进行替换为: #'foo/inc
nil
bar=> (inc 8)

IllegalStateException 尝试调用未绑定的函数: #'foo/inc clojure.lang.Var$Unbound.throwArity (Var.java:43)
`

进一步调查显示 foo/inc 是未绑定的

foo/inc
=> #

进一步调查还显示,将 (def inc inc) 替换为几乎任何其他内容,例如 (def inc dec),(def inc clojure.core/inc),或 (def inc (fn (link: n) (+ n 1))),都不会导致异常(但警告仍然存在)。

我预计
a) foo/inc 应该绑定并且具有与 clojure.core/inc 相同的值
b) 调用 foo/inc 时没有错误
c) bar/inc 应该绑定到 foo/inc

22 答案

0

评论者:bronsa

第二个错误应该预料到,正确的语法应该是 (require (link:'foo :refer ['inc]))(注意 inc 前面的引导引号)

0

评论由:mikera 提出

感谢指出错误,Nicola - 我已经编辑了描述。但是仍然出现相同的错误(只是消息略有不同)

0

评论由:alexmiller 提出

查看评论...

0

评论由:mikera 提出

@Alex 你在说什么评论?请注意,即使有正确的语法,错误仍然发生...

0

评论由:mikera 提出

似乎过早地关闭了

0

评论由:alexmiller 提出

我不能用正确的语法重现

`
Clojure 1.7.0-master-SNAPSHOT
user=> (ns foo)
nil
foo=> (def inc inc)
WARNING: inc 已经在命名空间 foo 中引用: #'clojure.core/inc,正在进行替换为: #'foo/inc

'foo/inc

foo=> (ns bar)
nil
bar=> (require ['foo :refer ['inc]])
WARNING: inc 已经在命名空间 bar 中引用:#'clojure.core/inc,正在进行替换为: #'foo/inc
nil
`

0

评论由:mikera 提出

问题是变量仍然未绑定,例如会导致以下错误

=> (foo/inc 8)
IllegalStateException 尝试调用未绑定的函数: #'foo/inc clojure.lang.Var$Unbound.throwArity (Var.java:43)

我认为这不应该发生 - 或者是我遗漏了什么?

0

评论由:alexmiller 提出

好的,我会看的,但现在不行:(

0

评论由:jafingerhut 提出

在描述中添加了一些更多信息。例如,如果你将 (def inc (fn (link: n) (+ n 1))) 替换为 (def inc inc),异常就会消失。警告仍然存在。

0

评论由:tcrayford 提供

不确定这是否是同一个问题(我认为可能是?),但是我已经使用AOT编译重现了相同的错误信息

在以下git仓库中重现了这个错误:https://github.com/yeller/compiler_update_not_referenced_bug

克隆它,运行 lein do clean, uberjar, test,错误信息将在我每次运行时都出现

0

评论由:jafingerhut 提出

Mike,我认为将你的例子中的 (def inc inc) 替换为 (def inc clojure.core/inc) 应该被视为这个问题的合理解决方案,除非你有某种用例需要将 inc 定义为一个不在 clojure.core 中的东西(如果是这样,为什么?)

(def inc inc)之所以会有这种行为,是因为它在Clojure程序中通常用于定义递归函数,例如(defn fib (n) (if (<= n 1) 1 (+ (fib (dec n)) (fib (- n 2))))),这样身体中的 fib 出现将解析为正在定义的 fib。

0

评论由:alexmiller 提出

转移到1.7,直到我能深入研究这个问题。

0

评论由:mikera 提出

Andy - 是的,当前这个解决方案对我来说是可行的。

我不认为这是一个紧急问题,但这个问题可能暴露了关于不同时间命名空间状态的潜在复杂性。也许语义可以是这样的:
- def 语句本身应该在 var 进驻之前运行。例如(def inc (inc 5))应该结果是(def inc 6)
- 在 def 语句完成后编译/延迟运行的任何内容应使用新的 var(即新的 var 应由函数、懒序列等引用)

0

评论由:jafingerhut 提出

我不确定在这样的情况下你的提议是什么意思

(def inc (fn [x] (inc x)))

第二个 inc 是否在创建新的 inc 之前或之后进行解析/解决?因为它是 (fn ...),所以应该先出现行为?还有什么除了 fn 外能导致这种行为,而不是预处理行为?

更有趣的是(不是说人们经常写出这样的代码,但编译器今天可以处理它)

`
(def inc (if (> (inc y) 5)

       (fn [x] (inc x))
       (fn [x] (dec x))))

`

我认为当前编译器行为'在 def 体的内部,定义的符号始终指的是新变量,而不是任何较早定义的变量'是相当容易解释的。

0

评论由:tcrayford 提供

我应该将在这件事中复现的 AOT 问题作为一个新问题提交吗?

...