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

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

0
Clojure

下面的代码会失败(在 1.6 和最新 1.7-alpha4 中都是一样)

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

'foo/inc

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

foo=> (ns bar)
nil
bar=> (require ['foo :refer ['inc]])
警告: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 dec),(def inc clojure.core/inc),或(def inc (fn (link: n) (+ n 1))) 替换(def inc inc),都不会导致异常(但警告仍然存在)。

我预计
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
by

由 alexmiller 发表的评论:

查看评论...

0
by

评论者:mikera

@Alex 哪条评论?注意,即使使用了正确的语法错误仍然发生...

0
by

评论者:mikera

看起来提前关闭了

0
by

由 alexmiller 发表的评论:

我无法用正确的语法来复现

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

'foo/inc

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

0
by

评论者:mikera

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

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

我认为这不应该预料到,或者是我在哪里遗漏了什么吗?

0
by

由 alexmiller 发表的评论:

好吧,我会看看的。但现在不行。 :)

0
by

由 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 clojure.core/inc)替换(def inc inc)可能是解决这个问题的合理方法,除非你有某些用例需要将inc定义为clojure.core之外的某个东西(如果是这样,为什么?)

(def inc inc)的行为方式的原因在于,如果不是绝对必要的,至少在Clojure程序中经常用于定义递归函数,例如(defn fib (link: n) (if (<= n 1) 1 (+ (fib (dec n)) (fib (- n 2))))),这样body中的fib出现会被解析为已定义的fib。

0

由 alexmiller 发表的评论:

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

0

评论者:mikera

安迪 - 对于我来说,这个解决办法现在的确是好的。

我认为这不是一个紧急问题,但它可能暴露了一个涉及关于不同时间命名空间状态的假设的微妙复杂性。也许语义应该类似于
- 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
by

评论人:tcrayford

我应该将该东西中复现的 AOT 问题作为新的问题提交吗?

...