Ocaml 如何使用尾部递归重写代码
我只是想寻求一些建议,如何使用尾部递归重写代码Ocaml 如何使用尾部递归重写代码,ocaml,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"; ;; 任何建议都会有帮
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";
;;
任何建议都会有帮助
let dig x =
let rec f x s =
match x with
| 0 -> s
| _ -> f (x-1) (x::s)
f x []
这是你想要的吗?它使用尾部递归
编辑:
对于递减序列,只需将(x::s)替换为(List.append s[x])或(s@[x]),但这不是一个好主意,List.rev更好:
let dig x =
let rec f x s =
match x with
| 0 -> s
| _ -> f (x-1) (s @ [x])
f x []
这是你想要的吗?它使用尾部递归
编辑:
对于递减序列,只需将(x::s)替换为(List.append s[x])或(s@[x]),但这不是一个好主意,List.rev更好:
let dig x =
let rec f x s =
match x with
| 0 -> s
| _ -> f (x-1) (s @ [x])
f x []
不确定这是否会使您的船漂浮:您可能需要调整边界情况,具体取决于您希望0还是包含起始编号
不确定这是否会使您的船漂浮:您可能需要调整边界情况,这取决于您是否想要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";
;;
多亏了大家,你帮了大忙。嗯,似乎可以有多种解决方案
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";
;;
感谢大家,您帮了很多忙。如果您不想在向后构建列表后使用
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
。我们用identity函数开始递归,因为我们还没有任何东西要构建。然后,当我们退出递归时,我们只需将空列表应用于获得的函数。如果您不想在向后构建列表(我认为这很好)后使用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
。我们用identity函数开始递归,因为我们还没有任何东西要构建。然后,当我们退出递归时,我们只需将空列表应用于获得的函数。这不是我想要的。您的函数生成递增序列,但我正在尝试创建递减序列。您应该使用List.rev
反转结果以保留顺序这不是我想要的。您的函数使用递增序列,但我正在尝试创建递减序列。您应该使用List来反转结果。rev
保留顺序l@[x]
使您的函数是二次的,而不是线性的:对于每个调用,您将遍历迄今为止为附加单个元素而构建的整个l
。此外,@
本身不是尾部递归的,因此实际上您正在将问题从digtail
转移到@
。您确实应该更喜欢Syeerzi的解决方案(使用ivg建议的最终List.rev
)l@[x]
使您的函数是二次函数而不是线性函数:对于每个调用,您都在遍历迄今为止为附加单个元素而构建的整个l
。此外,@
本身不是尾部递归的,因此实际上您正在将问题从digtail
转移到@
。你真的应该更喜欢Syeerzi的解决方案(使用ivg建议的最终List.rev
)你知道,这不是我不喜欢List.rev或内部递归函数的解决方案,我只是想找到更多的方法来解决这个简单的任务。我只是开始学习OCaml,想看看其他人如何在简单任务中使用它。(关于我的英语学习,我也能说同样的话。)我没问题。我只是想强调一个事实,前两个答案比我的更为惯用,这确实只是为了完整起见。“你可以使用某种延续”,也称为差异列表。你知道,这不是我不喜欢List.rev或内部递归函数的解,我只是想找到更多的方法来解决这个简单的任务。我只是开始学习OCaml,想看看其他人如何在简单任务中使用它。(关于我的英语学习,我也能说同样的话。)我没问题。我只是想强调一个事实,前两个答案比我的更为惯用,这确实只是为了完整起见。“你可以使用某种延续”,也称为差异列表。