请分享您的想法在 2024 年 Clojure 状态调查!

欢迎!请参阅 关于页面 了解关于如何操作的更多信息。

+1
错误

将 var 的定义放在不存在的 ns 中会产生这个错误

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

原因: 如果有资格的 var 中的 ns 还不存在,编译器 .lookupVar() 返回 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

2014年6月26日创建的补丁 clj-1400-1.diff 在2014年8月29日对Clojure进行某些提交后,不再干净地应用于最新的master。在那之前,它会干净地应用。

我没有检查更新此补丁是否容易或困难。有关更新补丁的提示,请参阅本页面的“更新过时的补丁”部分:http://dev.clojure.org/display/community/Developing Patches

0

由 scottbale 发布的评论

附件是更新的补丁:“clj-1400-2.diff”。我删除了过时的补丁。

0

评论人:alexmiller

有一些评论需要解决。
- 编译器差异使用了空间而不是制表符,这使得差异更难。我附上了-3.diff以解决这个问题。
- namesStaticMember 调用看起来很奇怪。这个方法的名称对这个用途来说很令人困惑。除此之外,我认为它做的事情比你需要的更多。这个方法将试图在当前命名空间中解析合格名称,但我认为你甚至不需要这样做。你只是想知道该 sym 是否有命名空间(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}} {{行}}和{{列}}参数不可用,或者至少不是afaict(as far as I am concerned)。

0

评论人:alexmiller

我稍后会跟进这个补丁 - Rich认为它做了太多的假设。我们认为我们已经验证了其中许多,但需要重新检查。

0

评论人:alexmiller

Clojure 1.10中的错误结果更新。现在它会抛出一个具有文件/行/列的编译语法错误阶段异常。

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