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

The second error should be expected, the right syntax should be (require (link: 'foo :refer ['inc])) (note the leading quote before 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

问题是这个var仍然未绑定,例如造成以下错误

=> (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定义到不在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语句后编译/延迟执行的任何内容都应使用新的变量(即函数、懒加载序列等应通过新变量引用)

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

...