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

评论由:alexmiller 提出

查看评论...

0

由 mikera 发表的评论

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

0

由 mikera 发表的评论

似乎关闭得太早了

0

评论由: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

由 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 提出

迈克,我认为在您的例子中将(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 语句完成后编译/延迟执行的内容应使用新变量(即新变量应被函数、懒加载序列等引用)

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的主体中,定义的符号始终引用新的var,而不是任何早期定义的var”是很容易解释的。

0

评论者:tcrayford

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

...