请在 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、target方面的不匹配?

0
评论者:bronsa_

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



FWIW '类型不匹配' 是编译器java用来描述这种情况的术语
0
参考: https://clojure.atlassian.net/browse/CLJ-1407(由bronsa报告)
...