2024 Clojure状态调查!中分享您的想法。

欢迎!有关如何使用本网站的更多信息,请参阅关于页面。

+1 投票
编译器

对短类名符号使用macroexpand会触发RuntimeException。

`
user=> (import 'java.net.URI)
java.net.URI
user=> (macroexpand '(java.net.URI "http://google.com")) ;; 正常
(java.net.URI "http://google.com")
user=> (macroexpand '(URI "http://google.com")) ;; 喂?
java.lang.RuntimeException: 期望变量,但URI已映射到类java.net.URI
user=> (pst *e)
RuntimeException 期望变量,但URI已映射到类java.net.URI

clojure.lang.Util.runtimeException (Util.java:221)
clojure.lang.Compiler.lookupVar (Compiler.java:7092)
clojure.lang.Compiler.isMacro (Compiler.java:6571)
clojure.lang.Compiler.macroexpand1 (Compiler.java:6626)
clojure.core/macroexpand-1 (core.clj:3870)
clojure.core/macroexpand (core.clj:3879)

`

这两个在宏展开期间都不应该抛出错误(基本上在展开后应该相同。它们在评估时应该抛出相同的错误(试图将类作为IFn调用)。

方法:只在没有找到变量的时候才在lookupVar中抛出运行时错误。在这种情况下,我们意外地找到了除了变量以外的其他内容,应该报告出来。否则,就让lookupVar继续执行,返回null(未找到变量)。

2 个答案

0 投票

评论由:alexmiller 发表

编译器正在尝试确定函数位置的元素是否为变量宏,该变量宏在Compiler.isMacro()中需要展开。

在(java.net.URI "http://google.com")的情况下,lookupVar确定java.net.URI是一个未映射的符号,因此不进行展开(这当然会在评估时失败,抛出"ClassCastException: java.lang.Class cannot be cast to clojure.lang.IFn"。

在(URI "http://google.com")的情况下,lookupVar找到一个符号,该符号映射到不是变量的东西,并抛出观察到的RuntimeException。

我预期在使用宏展开过程中,这两个都不会抛出错误(基本上和它们开始时一样),并且当它们被评估时,应该抛出相同的错误。附上一个补丁,该补丁只在 internNew 的情况下抛出错误(在这种情况下,你意外地发现除了 var 以外的东西,你应该仍然报告错误,否则只返回 null - lookupVar 没有找到 var)。

internNew 的情况会产生

(import java.net.URI) (def URI "abc") ;; java.lang.RuntimeException: 预期 var,但 URI 映射到类 java.net.URI

使用补丁后的结果

user=> (macroexpand '(java.net.URI "http://google.com")) (java.net.URI "http://google.com") user=> (macroexpand '(URI "http://google.com")) (URI "http://google.com") user=> (java.net.URI "http://google.com") ClassCastException 类 java.lang.Class 不能转换为 clojure.lang.IFn user/eval9 (NO_SOURCE_FILE:6) user=> (URI "http://google.com") ClassCastException 类 java.lang.Class 不能转换为 clojure.lang.IFn user/eval11 (NO_SOURCE_FILE:7)

0 投票
参考: https://clojure.atlassian.net/browse/CLJ-1759 (由 venantius 提出)
...