欢迎!请查阅 关于 页面了解这项工作的更多详细信息。
使用 core/proxy 为 Java 类生成代理会在生成的类文件中产生不可预测的方法顺序。这在可重复构建(编译时)时是一个问题。
具体来说,我正在 Docker 内运行 Clojure,并希望我的应用程序镜像层尽可能小,如同 Java 开发者使用 Meta-inf 类路径和 lib 目录创建的镜像。无论如何,为了让它正确工作,以便所有依赖项(包括作为 AOT 编译的一部分编译的依赖项)都在一个单独的层上,我需要在每次构建运行时都输出应用程序依赖项代理的编译结果相同。这可以减少构建时间、镜像推送时间、镜像拉取时间和容器调度时间。
示例代码表现了这个问题(您需要运行几次来看到问题)。
https://github.com/kipz/predictable-proxies
原因:我已经追踪到这里的未排序映射的使用
https://github.com/clojure/clojure/blob/master/src/clj/clojure/core_proxy.clj#L186
方法:使用排序映射,按键的哈希值排序(键是一个包含方法名、参数类型序列和返回类型向量的向量)。
修改:CLJ-1973-v5.patch
筛选者:Alex Miller
评论者:kipz
使用 sorted-map 的补丁
评论由:alexmiller发布
我认为您可以遵循https://clojure.org/guides/comparators上的建议,为这个补丁编写一个更简单的比较器。
如您所请求的,已简化比较器。
我认为您丢失了排序集合。
在不同分支间复制粘贴错误。这次测试过了。
现在使用了更一致的 'let' 格式化
虽然这可能是可以的,但可能更好的是用Clojure的hash函数而不是Java的hashCode函数。地图本身是基于hash进行散列的,所以这似乎更合适。
如您所请求的,现在使用Clojure的'hash'函数。
谢谢Alex - 还了解到了布尔比较器!
请注意,此顺序可能在不同版本的Clojure或JVM之间发生变化,因为这些没有跨版本保证的哈希值。目前先进行预审。