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

欢迎!有关如何使用此平台的更多信息,请参阅 关于 页面。

0
Clojure

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

`
user=> (ns foo)
nil
foo=> (def inc inc)
WARNING: inc 已在命名空间: foo 中使用,正被替换为: #'foo/inc

'foo/inc

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

foo=> (ns bar)
nil
bar=> (require ['foo :refer ['inc]])
WARNING: 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 已在命名空间: foo 中使用,正被替换为: #'foo/inc

'foo/inc

foo=> (ns bar)
nil
bar=> (require ['foo :refer ['inc]])
WARNING: 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发表

Mike,我认为将你的例子中的“(def inc inc)”替换为“(def inc clojure.core/inc)”应被视为解决此问题的合理方法,除非你有某种需要将inc def到不在clojure.core中的情况(如果是这样,原因是什么?)

“(def inc inc)”的行为方式是,如果不是绝对必要的,至少在Clojure程序中用于定义递归函数时是常见的,例如(defn fib (n)(if (<= n 1) 1 (+ (fib (dec n)) (fib (- n 2))))),这样在体中的fib出现会解析到定义的fib。

0

评论由:alexmiller发表

我将其移至1.7版本,直到我能更深入地研究这个问题。

0

评论由:mikera 提出

Andy - workaround对我来说现在很好。

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

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问题作为一个新问题提交吗?

...