如何使用尾递归重写代码

时间:2015-09-15 15:39:08

标签: ocaml

我只是在寻找一些建议,如何使用尾递归重写代码

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";
;;

任何建议都会有所帮助

4 个答案:

答案 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";
;;

感谢所有人,你帮了很多忙。