请在 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,以及使用 gen-class 的 ns
  • gen-interface,以及使用 gen-interface 的 definterface
  • 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,“类型不匹配”是编译器在 java 中用于描述这种情况的术语
0
参考:[https://clojure.atlassian.net/browse/CLJ-1407](https://clojure.atlassian.net/browse/CLJ-1407)(报告者:bronsa)
...