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

欢迎!请参阅简介页面获取有关如何操作的更多信息。

+1
编译器

原始函数和 recur 变量不能干净地通过 (try);它们被装箱成 Object 类型。这会导致使用原始类型的函数或循环产生反射警告。

`
user=> (set! warn-on-reflection true)
true

user=> (fn [] (loop [t 0] (recur t)))

<user$eval676$fn677 user$eval676$fn677@3d80023a>

user=> (fn [] (loop [t 0] (recur (try t))))
NO_SOURCE_FILE:1 recur 参数对于原始本地变量: t 不匹配原始值,拥有: Object,需要: long
自动装箱循环参数: t

<user$eval680$fn681 user$eval680$fn681@5419323a>

user=> (fn [^long x] (recur (try x)))
NO_SOURCE_FILE:1 recur 参数对于原始本地变量: x 不匹配原始值,拥有: Object,需要: long

编译器异常 java.lang.IllegalArgumentException: recur 参数对于原始本地变量: x 不匹配原始值,拥有: Object,需要: long,编译:(NO_SOURCE_PATH:1:1)
`

7 个回答

0

评论者:davidj

不讨论最理想的操作行为,以下代码不会产生反射警告

`
user=> (set! warn-on-reflection true)
true
user=> (fn [] (loop [t 0] (recur (long (try t)))))

<user$eval673$fn674 user$eval673$fn674@4e56c411>

`

0

评论者:bronsa

类似的问题http://dev.clojure.org/jira/browse/CLJ-701

0
by

评论由:hiredman

编译器中的 try/catch 只实现了 Expr,而不是 MaybePrimitiveExpr,看起来在 TryExpr 上扩展 MaybePrimitiveExpr 十分简单,但结果是 recur 分析了它在语句上下文中的参数,这导致 (try ...) 实际上像 ((fn (link: ) (try ...))) 一样包裹了自己,这时它就变成了 invokeexpr,这使得添加 maybeprimitiveexpr 变得更加困难,而且它与 CLJ-701 的案例相同

0
by

评论由:hiredman

http://dev.clojure.org/jira/browse/CLJ-701 有一个补丁,我认为它解决了这个问题

0
by

评论由:alexmiller

我应该将其复制到 CLJ-701 吗?

0
by

评论由:hiredman

如果你想要 try 退出上下文时的修复成为 CLJ-701 的部分,那么它就是一个重复,如果你不确定,或者更喜欢 701 保持更专注于(我的补丁可能不被接受,或者可能太大并且做得太多)那么它就不会是一个重复。我在 CLJ-701 上的补丁中稍微把它解决了,因为我是通过 Nicola 的评论来到 CLJ-701 的,并且相同的编译器机制可以用于两者。

我认为这取决于 CLJ-701 的状态。

0
by
参考:https://clojure.atlassian.net/browse/CLJ-1422(由 aphyr 报告)
...