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

感谢尼古拉的提醒 - 我已经编辑了描述。但是仍然出现相同的错误(只是消息稍微不同)

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 (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 (link: n) (if (<= n 1) 1 (+ (fib (dec n)) (fib (- n 2))))),这样代码体内出现的 fib 变量都能解析为正在定义的 fib。

0

评论由:alexmiller

将此问题移至1.7,直到我可以更深入地研究。

0

评论由:mikera

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

我认为这不是一个紧急问题,但它可能揭露了关于不同时刻命名空间状态的隐含复杂性。也许语义应该是这样的:
- 在 var 入射之前,应该先运行 def 语句。例如,(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问题作为新问题提交吗?

...