recursion - 为什么这不会在 mapcat 中再次发生终止?
问题描述
为什么 this inside 不recur
终止mapcat
,而命名fn
调用版本等效呢?
(def tree [1 [2 [3 5]] [6 [[1 2] [8 [9 10]]]]])
(defn leaves
[node]
(mapcat #(if (vector? %) (leaves %) [%]) node))
(leaves tree)
;; => (1 2 3 5 6 1 2 8 9 10)
(defn leaves-with-recur
[node]
(mapcat #(if (vector? %) (recur %) [%]) node))
(leaves-with-recur tree)
;; Never terminates
如果这样的使用recur
是一个直接的禁忌,那么 Clojure 编译器是否有任何理由不应该捕捉到这种情况并警告程序员,或者甚至拒绝编译它?例如,非尾部位置调用就是这种recur
情况。
解决方案
#(if (vector? %) (recur %) [%])
是的简写
(fn [%]
(if (vector? %)
(recur %)
[%]))
这recur
将递归到这个匿名函数,而不是任何外部函数,并且由于它不会改变任何东西,这是一个无限循环。
至于警告——众所周知,停止问题是无法解决的,即使只是尝试实施一些启发式方法,在编译时也有陷入死循环的风险。
推荐阅读
- r - R 编程:当父母被移除时,悬空的子环境会发生什么?
- python - |U 和 U 关于字符串的 numpy dtype 说明符有什么区别
- javascript - 使用 AJAX 更改 iFrame Google Maps Src 标签
- asp.net-mvc - 来自外部帖子的路由视图
- python - 用户变量如何传递给主视图模板
- javascript - 在 box-shadow 属性上禁用 CSS 过渡
- python - 在 PyQtGraph 中设置 zValue
- python - 在 Python 中对回归函数使用详尽的优化算法
- docker - 将容器端口暴露给特定主机 IP
- java - Loaders 与 BroadcastReceivers 的优先级在主线程上启动