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

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

+1
错误

使用一个不存在的命名空间定义变量将产生此错误

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

原因: 如果限定变量中的命名空间尚不存在,则 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: Qualified symbol foo/bar refers to nonexistent namespace: foo, compiling:(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

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

我尚未检查更新此补丁的难易程度。有关更新补丁的提示,请参阅本维基页面上的“更新陈旧补丁”部分: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
Aug 23, 2019 • 11:24 AM

由:scottbale 评论

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

我不确定 Compiler.java 中的哪个 try-catch 块会导致这种情况,因为有多个。但是你可以在输出中看到异常是 CompilerException,并且有文件|行|列信息。

在 Repl...

user> (def foo/bar 1) CompilerException java.lang.RuntimeException: Qualified symbol foo/bar refers to nonexistent namespace: foo, compiling:(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
Aug 23, 2019 • 11:24 AM

评论人:alexmiller

我会在之后跟进这个补丁 - Rich 认为它做了太多假设。我认为我们已经验证了许多这些假设,但需要再次核对。

0
by

评论人:alexmiller

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

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