请在 2024 年 Clojure 状态调查! 分享您的想法。

欢迎!请查看 关于 页面了解此工作的更多详细信息。

0
编译器

由于不匹配的递归(在循环体中与循环参数具有不同推断类型的局部变量)导致重新分析循环体,循环体中的宏展开可能会发生多次,导致在宏展开期间发生的任何副作用可能被评估多次。

`
Clojure 1.7.0-master-SNAPSHOT
user=> (defmacro x [] (println "foo"))

'user/x

user=> (fn [] (loop [y 1] (x) (recur (Integer. 1))))
foo
foo

<user$eval6$fn7 user$eval6$fn7@71687585>

`

6 答案

0

评论由 jafingerhut 发布

这不是一个关于描述中的行为是否为错误的讨论,而是一个关于人们编写具有宏展开时副作用的宏的频率的好奇。我认为以下在 Clojure 本身中是这样做的,但也可能有其他的

  • gen-class,以及 ns 因为它使用 gen-class
  • gen-interface,以及 definterface 因为它使用 gen-interface
  • clojure.core/compile-if (私有) 在它的 expr 参数上调用 eval,但现在使用的情况下不会导致宏展开时的副作用
  • doc 似乎在宏展开时打印了一个情况
  • 我不确定 defprotocol 或 deftype 是否具有宏展开时的副作用,或它们是否仅限于运行时
0

评论由 bronsa 发布

Andy,我不认为有那么多在宏展开时有副作用的宏,我还没有在实际代码中发现这个错误,但是当我思考 Compiler.java 中如何实现循环变量无效化时。

因为有这么少的副作用宏,所以不太可能在实际代码中引起问题,所以我将其优先级改为较小。

0

评论者:arcatan

关于现实意义的评论:Cloverage,Clojure代码覆盖率工具,严重依赖于具有副作用的语言宏,这个错误导致我经常得到错误的覆盖率结果。我在(链接:https://github.com/cloverage/cloverage/issues/240,文本:Cloverage问题跟踪器)上发表了关于此事的帖子。

0

评论者:admin

什么是“不匹配的递归”?能否表述得更精确一些?类型、arity还是目标的“不匹配”?

0
由:bronsa_

类型不匹配,票证中的示例显示了从long到Integer的本地切换



FWIW‘类型不匹配’是在Compiler.java中用来指代这种情况的术语
0
参考资料:https://clojure.atlassian.net/browse/CLJ-1407(由bronsa报告)
...