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

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

+1 投票
编译器

这是我从电子邮件列表上https://groups.google.com/forum/#!topic/clojure/Ozt5HQyM36I上的帖子。基于那里的回复,我不确定这是应该记录为增强功能还是错误。请改为适当的标签。

我在使用ns-unmap时发现AOT编译的Clojure中似乎有一个错误;这个根本原因可能影响到其他重新定义Vars的代码。以下是我的简化示例:

(ns unmap-test.core)

(def a :test-1)

(ns-unmap 'unmap-test.core 'a)

(def a :test-2)

结果是,当这个命名空间加载时,a无法解析。当我查看编译的字节码时,
出现以下操作:

  1. 调用 RT.varwith 'unmap-test.core 和 'a 返回一个 Var,该 Var 绑定到一个常量。
    在此调用期间将此 Var 添加到命名空间的映射中。
  2. 与1相同。
  3. 将第一个步骤中的 Var 绑定到 :test-1。
  4. 调用ns-unmap。
  5. 将第二个步骤中的 Var 绑定到 :test-2。

免责声明:这是我第一次直接查看字节码,我可能遗漏了什么。

这里的基本问题是 Var 可从加载方法访问,但当执行第五步时,Var 就无法从命名空间映射中访问了。
因此,Var 的根设置为 :test-2,但该 Var 未从命名空间映射。
在没有 AOT 编译的情况下,这也可以工作,以及当我使用

(ns unmap-test.core)

(def a :test-1)

(ns-unmap 'unmap-test.core 'a)

(intern 'unmap-test.core 'a :test-2)

时。我意识到在 Clojure 中创建定义、取消映射并重新创建它们是一种不良的实践。
我们有这样一个怪异的情况:我们需要在同一命名空间中有一个接口和一个同名 Var。简单
地对definterface 和def 做出definterface 和然后定义将导致编译失败

user=> (definterface abc)
user.abc
user=> (def abc 1)
CompilerException java.lang.RuntimeException: 期望 Var,但 abc 被映射到接口 user.abc,编译:(private/var/folders/3m/tvc28b5d7p50v5_8q5ntj0pmflbdh9/T/form-init4734176956271823921.clj:1:1)

不深入细节,这是一个基本上的漏洞,允许我们对内部框架代码进行重构
而不立即更改大量下游消费者代码。我们消除了宏展开期间的使用接口
但它仍然需要存在于类路径中,以便由下游命名空间导入。
有几种其他方法可以实现这一点,因此这对我们来说不是一个大问题,但我认为这个问题值得提出。
这只是我尝试的第一件事,对此不起作用,我感到惊讶。

请注意,我在我的示例项目中使用了Clojure的1.8.0 RC4版本,但我在1.7.0版本上也观察到了相同的行为。

相关链接

  1. 初始化类的load方法的字节码: https://gist.github.com/WilliamParker/d8ef4c0555a30135f35a
  2. init0方法的字节码: https://gist.github.com/WilliamParker/dc606ad086670915efd9
  3. 初始化类的反汇编Java代码。请注意,据我所知,这与字节码不完全一致,
    但与字节码相比,它是一种更快地了解发生了什么的方法。
    https://gist.github.com/WilliamParker/4cc47939f613d4595d94
  4. 包含上述代码的简单项目: https://github.com/WilliamParker/unmap-test
    请注意,如果您不使用AOT编译尝试,则应删除包含任何先前编译类的目标文件夹。

4 个答案

+1 投票

评论由:bronsa

这个问题与CLJ-1604中的问题类似,提出的补丁将修复范围扩展到所有变量,而不仅仅是clojure.core变量。

+1 投票

评论由:hiredman

这个是由clj-1604修复的吗?

+1 投票

评论由:bronsa

不,CLJ-1604仅处理clojure.core的Vars,此处附加的补丁是在对CLJ-1604提交的补丁之上进行扩展,该补丁处理其他命名空间。

0
参考:https://clojure.atlassian.net/browse/CLJ-1874(由alex+import报告)
...