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

欢迎!有关如何运作的更多信息,请参阅关于页面。

+1
错误

定义不存在命名空间中的变量的定义将产生此错误

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

原因:如果合格变量中的命名空间不存在,则 Compiler.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日发布的patch 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

有几个评论需要处理
- 编译器比较使用的是空格,而不是制表符,这使得比较更难。我附上一个-3.diff,修复了这个问题。
- namesStaticMember的调用看起来很奇怪。该方法的名称对于这种用途来说是混乱的。除此之外,我认为它做了更多不必要的操作。该方法将尝试在当前ns中解析限定名称,但我想你甚至不需要这样做。而是你只需要知道sym是否有ns(sym.ns != null) - 不够了吗?
- 在什么情况下将会出现其他错误“变量不存在”?换句话说,在什么情况下lookupVar不能在这里创建一个新的变量?如果没有这种情况,那么就删除这个情况。如果有这种情况,那么添加一个测试。

0

评论:scottbale

同意你的三个要点。附上了更新过的补丁, clj-1400-4.diff。
我在 Compiler.java 中使用了制表符
经过对 lookupVar(...) 调用的详细检查后,我认为仅在此票据的情况下返回 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、line 和 col 参数不可用,或者至少据我所知是这样的。

0

评论者:alexmiller

我将在稍后跟进此补丁 - Rich 认为它做了太多假设。我认为我们已经验证了许多假设,但需要再次检查这些假设。

0

评论者:alexmiller

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

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