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

欢迎!请参阅 关于 页面以获取更多有关如何使用此网站的介绍。

+1
错误

如果 ns 不存在,定义变量的声明会产生此错误

user> (def foo/bar 1) 编译错误:在 (REPL:1:1) 编译 def 时出错。不能在当前 ns 之外创建定义

原因: 编译器 .lookupVar() 如果合格变量中的 ns 尚不存在,则返回 null。

建议: 通过命名符号并抛出带有文件/行/列信息的 CompilerException,可以提高错误消息的质量。这不是很明显,但这可能是唯一发生此错误的情况。如果是这样,错误消息可以更具体地指示 ns 是不存在的那部分。

补丁: 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: 有资格的符号 goo/bar 引用了不存在的命名空间:goo,编译:(/home/scott/dev/foo.clj:3:1)

0

评论者:jafingerhut

补丁 clj-1400-1.diff 日期为 2014 年 6 月 26 日,在 2014 年 8 月 29 日对 Clojure 进行几项提交后,已无法干净地应用于最新的 master。在那一天之前,它可以干净地应用。

我没有检查更新此补丁的难易程度。请参阅此维基页面上的“更新过期补丁”部分,了解有关更新补丁的一些提示:[http://dev.clojure.org/display/community/Developing+Patches](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(... )的调用进行仔细检查后,我认为仅在这种情况下返回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: 有资格的符号 goo/bar 引用了不存在的命名空间:goo,编译:(/home/scott/dev/foo.clj:3:1)

此外,在这个补丁的RuntimeException被抛出的点,CompilerException的{{source}} {{line}}和{{col}}参数不可用,至少据我所知。

0

评论者:alexmiller

我稍后会跟进这个补丁 - Rich认为它有很多假设。我认为我们验证了许多那些,但需要再次核对。

0
by

评论者:alexmiller

截至 Clojure 1.10 更新错误结果。现在它会产生一个带有文件/行/列的编译语法错误阶段的异常。

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