在<.sax鞘: href="https://www.surveymonkey.com/r/clojure2024">2024 Clojure状态调查!

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

0
Clojure

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

`
user=> (ns foo)
nil
foo=> (def inc inc)
WARNING: inc 已经在命名空间foo中指向: #'clojure.core/inc,正被替换为: #'foo/inc

'foo/inc

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

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

'foo/inc

foo=> (ns bar)
nil
bar=> (require ['foo :refer ['inc]])
WARNING: inc 已经在命名空间bar中指向: #'clojure.core/inc,正被替换为: #'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)应该被视为解决此问题的合理方法,除非你有一些需要将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)))

第二个 inc 是在选择该定义之前还是之后被解析/解决的?因为它是 (fn ...),应该是有这种在之后的处理行为?还有什么东西除了 fn 会导致这种在之后的处理行为,而不是在之前的行为?

更有趣的是(不意味着人们经常这样写代码,但是编译器今天能处理它)

`
(def inc (if (> (inc y) 5)

       (fn [x] (inc x))
       (fn [x] (dec x))))

`

我认为当前的编译器行为“在 def 的体内部,定义的符号总是指向新的变量,而不是任何之前的定义的变量”是相当容易解释的。

0
答:

评论者:tcrayford

我应该在该事物中复制的 AOT 问题作为新问题报送吗?

...