如何对返回元组的OCaml split_at函数进行尾调用优化?
让OCaml的split_at函数用常量栈空间的优化方案
你的split_at函数目前无法通过@tail_mod_cons优化的原因很明确:tail_mod_cons仅针对**直接返回列表构造(h :: 递归调用)**的场景做优化,而你的函数返回的是元组((h :: left), right),递归调用的结果被用来构造元组的第一个元素,不属于tail_mod_cons的适用范围。
要实现常量栈空间的优化,你可以改用带累加器的尾递归版本,通过反向收集左半部分元素,最后再反转得到正确顺序:
let split_at ls i = let rec aux ls i acc = match i with | 0 -> (List.rev acc, ls) | _ -> match ls with | [] -> raise Not_found | h::t -> aux t (i-1) (h::acc) in aux ls i []
这个版本的aux函数是严格尾递归的:每次递归调用都是函数的最后一个操作,OCaml编译器会自动将其优化为循环,完全不消耗栈空间。
另外补充一点:如果你的OCaml版本较新(4.14+),可以尝试给原函数加上[@tail_mod_cons]属性并开启编译优化(-O3),但实际测试下来,由于返回值是元组而非直接的列表构造,编译器依然无法触发优化。所以带累加器的尾递归是最可靠的方案。
内容的提问来源于stack exchange,提问作者mushroom
相关产品推荐
相关产品推荐

