欢迎!请参阅 关于 页面了解此处的更多操作信息。
我在 cloth.core 中的一些地方看到了以下模式
(if (next more) (recur ... (next more)) ...)
其中 `next` 在 `recur` 调用之前被调用了两次。
这是“设计”的吗,还是仅仅是未被注意到的代码?
我预期会有更高效的实现,例如
(if-let [next' (next more)] (recur ... next') ...)
可能是为了避免“掌握序列的头部”的风险。在一般情况下,您希望在递归调用之前,序列已被消耗的部分可被垃圾收集。
这可能是在 core 中定义函数的顺序吗?
浏览 core.clj 文件时,发现 if-let 宏实际上定义在第 1841 行
if-let
https://github.com/clojure/clojure/blob/653b8465845a78ef7543e0a250078eea2d56b659/src/clj/clojure/core.clj#L1841
而 “next more recur next more” 片段(数学材料中)在使用 let 或 if-let 存在之前就被使用了(第 1055 行)
let
https://github.com/clojure/clojure/blob/653b8465845a78ef7543e0a250078eea2d56b659/src/clj/clojure/core.clj#L1055
defmacro if-let 之后的部分实际上使用的是您预期的模式(第 3690 行)
defmacro if-let
https://github.com/clojure/clojure/blob/653b8465845a78ef7543e0a250078eea2d56b659/src/clj/clojure/core.clj#L3690
我认为这里使用的是与正常 clojure 代码一样的常规单遍编译,函数必须在您使用之前定义,无论是宏还是 defns。
我不确定为什么顺序必须这样,可能和启动有关。
我建议您使用 Criterium 库比较当前版本和修改后的函数版本的性能基准测试,看看是否能够得到更快的结果,Criterium 库用来在 Clojure/Java 上进行性能测量: https://github.com/hugoduncan/criterium
我还没有进行过这样的测量,但 HotSpot JIT 编译器有时可以做一些非常惊人的事情。