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投票
by

评论者:arcatan

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

0投票
by

评论者:admin

什么是“不匹配的递归”?这能否更精确一点?类型、参数或目标的“不匹配”?

0投票
by
评论者:bronsa_

类型不匹配,查票中的例子展示了一个局部变量从 long 切换到 Integer



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