我只是在寻找一些建议,如何使用尾递归重写代码
open Core.Std;;
let rec dig x =
match x with
| 0 -> []
| _ -> x :: dig (x - 1)
;;
let () =
let numbers = dig 10 in
List.iter ~f:(Printf.printf "%d, ") numbers;
Printf.printf "\n";
;;
任何建议都会有所帮助
答案 0 :(得分:3)
let dig x =
let rec f x s =
match x with
| 0 -> s
| _ -> f (x-1) (x::s)
f x []
这是你想要的吗?它使用尾递归。
编辑: 对于减少的seq,只需用(List.append s [x])或(s @ [x])替换(x :: s),但这不是一个好主意,而List.rev更好:
let dig x =
let rec f x s =
match x with
| 0 -> s
| _ -> f (x-1) (s @ [x])
f x []
答案 1 :(得分:1)
let dig x =
let rec f s z =
if z = x then s
else f (z::s) (z+1)
in
f [] 0
不确定这是否漂浮在您的船上:您可能需要调整边框情况,具体取决于您是否需要0或包含起始编号。
答案 2 :(得分:1)
如果您在向后构建列表后不想使用List.rev
(在我看来完全没问题),也不要使用0
代替n
开始递归,你可以使用某种延续:
let dig2 x =
let rec aux x kont =
match x with
| 0 -> kont
| _ -> aux (x-1) (fun l -> kont (x::l))
in
aux x (fun l -> l) [];;
基本上每个步骤都会返回一个函数,在给定其余步骤构建的列表的情况下,该函数会向其追加x
。我们用身份函数开始递归,因为我们还没有任何东西可以构建。然后,当我们退出递归时,我们只需要将空列表应用于获得的函数。
答案 3 :(得分:0)
好吧,似乎可以有多种解决方案
open Core.Std;;
let rec digtail ?(l=[]) x =
match x with
| 0 -> l
| _ -> digtail ~l: (l @ [x]) (x - 1)
;;
let () =
let numbers = digtail 10 in
List.iter ~f:(Printf.printf "%d, ") numbers;
Printf.printf "\n";
;;
感谢所有人,你帮了很多忙。