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 (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 中引用: #'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

问题在于 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

迈克,我认为在您的例子中将(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语句后,任何编译或延迟执行的 textBox 应使用新的 var(即新的 var 应由 fn、lazy sequences 等引用)

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

...