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

欢迎!请参阅关于页面以了解更多有关本站如何运作的信息。

0 投票
Clojure

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

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

'foo/inc

;; 注意 inc 在这个点上未绑定,这导致了下面的异常
foo=> inc

foo=> (ns bar)
nil
bar=> (require ['foo :refer ['inc]])
WARNING: inc 已经引用了:#'clojure.core/inc 在命名空间:bar,将被替换为:#'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 投票
by

评论由:alexmiller

查看评论...

0 投票
by

评论由:mikera 撰写

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

0 投票
by

评论由:mikera 撰写

似乎关闭过早了

0 投票
by

评论由:alexmiller

我无法在正确的语法下重现

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

'foo/inc

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

0 投票
by

评论由:mikera 撰写

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

=> (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

Mike,我认为将例子中的 (def inc inc) 替换为 (def inc clojure.core/inc) 应该被视为对该问题的合理解决方案,除非你有某些使用场景需要将 def 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 撰写

Andy - 对我现在的解决方案来说,这是一个合适的解决方案。

我认为这不是一个紧急的问题,但它可能揭示了关于不同时期命名空间状态假设的微妙复杂性。也许语义应该如下
- 表达式 def 应在 var 被插入之前运行 (在)。例如 (def inc (inc 5)) 应该导致 (def inc 6)
- 在 def 语句完成之后编译/延迟执行的内容应使用新的 var(即新的 var 应由函数、懒序列等引用)

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问题作为新问题报告吗?

...