List.fold_right
不是tail-recursive
http://caml.inria.fr/pub/docs/manual-ocaml/libref/List.html
我的问题是为什么List.fold_right
未实现为tail-recursive
?
我认为这样做并不难
let rev l =
let rec revr acc = function
| [] -> acc
| hd::tl -> revr (hd::acc) tl
in
revr [] l;;
let fold_right f l b =
let rev_l = rev l
in
let rec folder_rr acc = function
| [] -> acc
| hd::tl -> folder_rr (f hd acc) tl
in
folder_rr b rev_l;;
我还在库中发现,许多函数不是tail-recursive
,而它们可以实现为tail-recursive
。 制造商是如何做出这样的决定的?
答案 0 :(得分:8)
这种尾递归实现可以将fold_right
应用于更大的列表,但代价是较短的列表较慢,因为您必须遍历列表两次。最初的开发人员认为,允许列表的极端用例(如果你有数千个元素,你应该计划更高效的数据结构),代价是丑陋的代码并且让其他人的表现更糟,这不是一个很好的权衡
有许多不同的方法可以使用尾递归映射,fold_right等。您可以在库中找到它们,扩展标准库,古老的Extlib和更新的电池和核心。实现技术从你的,到使用非tailrec版本乐观地使用前几千个项目的技巧,然后切换到tailrec版本,以丑陋的不安全技巧进行单次遍历以牺牲细胞突变为代价(这也会降低表现。)
答案 1 :(得分:8)
此问题之前已被问过,可能很多次。您可以在此处阅读以前的一些答案:
Why does the OCaml std lib have so many non-tail-recursive functions?
我的快速回答是,对于小型病例,非尾递归实现通常要快得多。实施者显然认为这是一个很好的权衡。