2024 Clojure 状态调查!中分享您的观点。

欢迎!请参阅关于页面获取更多有关该功能的信息。

0
Clojure

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

`
user=> (ns foo)
nil
foo=> (def inc inc)
WARNING: inc already refers to: &'clojure.core/inc in namespace: foo, being replaced by: &'foo/inc

'foo/inc

;; 注意,inc 此时未绑定,从而导致以下异常
foo=> inc

foo=> (ns bar)
nil
bar=> (require ['foo :refer ['inc]])
WARNING: inc already refers to: &'clojure.core/inc in namespace: bar, being replaced by: &'foo/inc
nil
bar=> (inc 8)

IllegalStateException Attempting to call unbound fn: &'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) 在 require foo/inc 时没有错误
c) bar/inc 应该绑定到 foo/inc

22 个答案

0

评论者:bronsa

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

0

评论者:mikera

感谢尼古拉的发现 - 我已编辑了描述。然而,错误依然存在(只是消息略有不同)。

0

由 alexmiller 发布的评论:

查看评论...

0

评论者:mikera

亚历克斯,哪条评论?注意,即使在正确的语法下,错误仍然存在...

0

评论者:mikera

似乎过早地关闭了。

0

由 alexmiller 发布的评论:

我无法用正确的语法来重现它。

`
Clojure 1.7.0-master-SNAPSHOT
user=> (ns foo)
nil
foo=> (def inc inc)
WARNING: inc already refers to: &'clojure.core/inc in namespace: foo, being replaced by: &'foo/inc

'foo/inc

foo=> (ns bar)
nil
bar=> (require ['foo :refer ['inc]])
WARNING: inc already refers to: &'clojure.core/inc in namespace: bar, being replaced by: &'foo/inc
nil
`

0

评论者:mikera

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

=> (foo/inc 8)
IllegalStateException Attempting to call unbound fn: &'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 发布的评论:

迈克,我认为在你的示例中将 (def inc inc) 替换为 (def inc clojure.core/inc) 应该是处理这个问题的合理方案,除非你有一些用例需要将 inc 定义为不在 clojure.core 中的某个东西(如果是的话,为什么?)

(def inc inc) 为什么会有这种行为的原因是,如果不是绝对必要的,那么在 Clojure 程序中至少常用作定义递归函数,例如 (defn fib (link: n) (if (<= n 1) 1 (+ (fib (dec n)) (fib (- n 2))))),以便将体中的 fib 出现解析为正在定义的 fib。

0

由 alexmiller 发布的评论:

转移到 1.7 直到我能更深入地查看这个问题。

0

评论者:mikera

安迪 - 目前针对我来说,这个解决方案是可行的。

我认为这不是一个紧急问题,但它可能会暴露关于不同时刻命名空间状态的假设的一些微妙复杂性。也许语义可以是这样的
- def 语句本身应该在 var 被内联之前运行。例如 (def inc (inc 5)) 应该产生 (def inc 6)
- 在 def 语句完成后编译/推迟运行的所有内容都应使用新的 var(即新的 var 应由 fns、懒序列等引用)

0

由 jafingerhut 发布的评论:

我不太清楚你的建议在类似这个案例中的含义

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

第二增量是在创建新增量之前还是之后进行解释/解决?因为它是一个(fn ...),它应该是在之后的行为?什么除了fn之外还能导致后续行为,而不是前置行为?

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

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

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

`

我认为当前编译器对'def体中的定义符号始终指向新变量,而不是任何先前定义的变量'的行为相当直观简单。

0

评论者:tcrayford

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

...