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 arg上调用eval,但现在使用不会引起宏展开时的副作用
  • doc似乎有一个在宏展开时打印的情况
  • 我不确定defprotocol或deftype是否有宏展开时的副作用,或者它们是否仅限于运行时
0

由:bronsa 评论

Andy,我不认为有很多宏在宏展开时会产生副作用,而我还没有在实际代码中发现这个错误,但是当我思考Compiler.java中循环局部变量失效的实现方式时,我想到了这一点。

因为产生副作用的项目式宏观数量非常少,这在实际代码中不太可能引起问题,所以我将其优先级降低为次要问题。

0

评论者:arcatan

关于实际意义进行评论:Cloverage,Clojure代码覆盖率工具,高度依赖于产生副作用的宏观,而这个错误导致我经常得到损坏的报告结果。我在(链接:https://github.com/cloverage/cloverage/issues/240 文本:Cloverage的问题跟踪器)上发帖讨论了这个问题。

0

评论者:admin

“不匹配的递归”是什么意思?能否更加精确?是在类型、参数数量还是目标上不匹配?

0
_评论者:bronsa_

类型不匹配,工单中的示例显示从 long 到 Integer 的局部切换



FWIW(仅供参考),在 Compiler.java 中使用“类型不匹配”这个术语来指代这种情况
0
参考:https://clojure.atlassian.net/browse/CLJ-1407(由bronsa报告)
...