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 发布的评论:

关于 [CLJ-701](http://dev.clojure.org/jira/browse/CLJ-701),有一个补丁我认为解决了这个问题。

0
by

由 alexmiller 发布的评论:

我应该将此内容复制到 CLJ-701 吗?

0
by

由 hiredman 发布的评论:

如果想在 CLJ-701 中包含 try 语句的修复,那么它是重复的;如果您不确定或者更希望 701 保持更集中的关注(我的补丁可能不被接受,或者可能太大且功能过多)那么它不是重复的。我尝试在一个 CLJ-701 的补丁中同时解决这个问题,因为我是通过 Nicola 的评论到达 CLJ-701 的,并且相同的编译器机制可以被用于两方面。

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

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