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

欢迎!请查阅关于页面获取有关此工作的一些更多信息。

+1
错误

定义一个不存在的命名空间中的变量的会得到这个错误

user> (def foo/bar 1) 编译错误,编译 def 于 (REPL:1:1)。当前命名空间外无法创建定义

原因: 编译器的 lookupVar() 方法在合格变量中命名空间不存在时会返回 null。

建议: 错误信息如果能命名符号并抛出包含文件/行/列信息的 CompilerException,则将得到改进。这不是显而易见的,但这可能是唯一发生此类错误的情况。如果是,则错误信息可以更具体地说明命名空间部分不存在。

补丁: clj-1400-4.diff

筛查者: Alex Miller

14 个答案

0

评论由:scottbale 发布

这在我看来似乎很容易解决,除非我遗漏了什么;分配给自己。

0

评论由:scottbale 发布

将补丁 {{clj-1400-1.diff}} 应用于 {{Compiler.java}}。

使用这个补丁,示例现在看起来如下

user> (def foo/bar 1) CompilerException java.lang.RuntimeException: 合格符号 foo/bar 指向不存在的命名空间:foo,编译:(NO_SOURCE_PATH:1:1)

我不确定 {{if(namesStaticMember(sym))}} (链接:见下文),和第二个分支是否真的必要。仅仅从视觉上看,我怀疑它可能不是这样的。

(链接:脚注)

`
public static boolean namesStaticMember(Symbol sym){

return sym.ns != null && namespaceFor(sym) == null;

}
`

0

评论由:scottbale 发布

补丁:代码和测试

0

评论由:scottbale 发布

我在实际源文件上进行了测试,异常信息中包含了所需的文件/行/列信息。

user=> CompilerException java.lang.RuntimeException: Qualified symbol goo/bar refers to nonexistent namespace: goo, compiling:(/home/scott/dev/foo.clj:3:1)

0

评论者:jafingerhut

2014年6月26日创建的“clj-1400-1.diff”补丁,在2014年8月29日对Clojure进行一些提交之后,无法干净地应用到最新的master分支上。在那一天之前,它可以干净地应用。

我尚未检查更新此补丁的可能难易程度。有关更新补丁的提示,请参阅本wiki页面的“更新过时的补丁”部分:http://dev.clojure.org/display/community/Developing Patches

0

评论由:scottbale 发布

附上更新后的补丁:“clj-1400-2.diff”。我已移除过时的补丁。

0

评论者:alexmiller

只有少量评论需要处理
- 编译器diff使用的是空格,而不是制表符,这使得diff更困难。我附上了纠正此问题的-3.diff。
- namesStaticMember的调用似乎很奇怪。这个方法的名称对于这个用途来说很令人困惑。除此之外,我认为它比所需的做得更多。该方法将尝试以当前ns的形式解析限定名称,但我觉得您甚至不需要这样做。相反,您只是想知道sym是否有ns(sym.ns != null)——不就足够了吗?
- 在什么情况下会触发其他错误“变量不存在”?换句话说,在什么情况下lookupVar无法在这里创建一个新的变量?如果没有这种情况,则删除此情况。如果有这种情况,则添加一个测试。

0

评论由:scottbale 发布

赞同你列举的所有三点。附件中包含了一个更新的补丁,clj-1400-4.diff。
我在Compiler.java中使用制表符 在对lookupVar(...)的调用的仔细检查后,我相信只有在 exactly this ticket(符号具有尚未加载的非null命名空间)的情况下才会返回null。所以我移除了条件分支和第二个分支。
*(测试不变)

0

评论由:scottbale 发布

(命名正确的补丁)

0

评论者:alexmiller

你可以像票据描述建议的那样抛出带有问题位置的CompilerException。

0

评论由:scottbale 发布

抱歉,我应该提到的,因为这也对我来说并不明显(实际上我直到刚才才想到):RuntimeException已经被捕获并封装在CompilerException中。

我不确定这是在Compiler.java中的哪个try-catch块发生的,有多个。但是你可以从输出中看到异常是CompilerException,并且有文件|行|列信息

在Repl...

user> (def foo/bar 1) CompilerException java.lang.RuntimeException: 合格符号 foo/bar 指向不存在的命名空间:foo,编译:(NO_SOURCE_PATH:1:1)

...或者在一个源文件中

user=> CompilerException java.lang.RuntimeException: Qualified symbol goo/bar refers to nonexistent namespace: goo, compiling:(/home/scott/dev/foo.clj:3:1)

此外,在这个补丁的RuntimeException被抛出的点上,CompilerException的source行和列参数不可用,至少在一定程度上是这样。

0

评论者:alexmiller

我将在稍后跟进这个补丁 - Rich认为它做了太多的假设。我想我们验证了很多,但还需要仔细检查。

0

评论者:alexmiller

截至 Clojure 1.10 更新了错误结果。现在正在抛出包含文件/行/列的 :compile-syntax 错误阶段异常。

0
参考: https://clojure.atlassian.net/browse/CLJ-1400(由 hlewisship 报告的)
...