我有这两个功能
//Remove all even indexed elements from a list and return the rest
let rec removeEven l =
match l with
| x0::x1::xs -> x1::removeEven (xs)
| [] -> []
| [_] -> []
//combine list members into pairs
let rec combinePair l =
match l with
| x0::x1::xs -> (x0,x1) :: combinePair(xs)
| [] -> []
| [_] -> []
那项工作。
但我现在想到的是,我不得不了解一下尾部递归,我很难掌握它。
这就是为什么我认为如果我能得到一些帮助来制作函数我自己的尾递归也许会更清楚它是如何工作的,而不是在某个地方读一些我可能不理解的例子以及我自己的代码(记住,我是一个完整的f#新手:))
关于我的代码的任何其他建设性意见当然是最受欢迎的!
答案 0 :(得分:3)
在F#中使函数尾递归的典型方法是使用列表(在这种情况下为acc
)来累积结果并将其反转以获得正确的顺序:
let removeEven l =
let rec loop xs acc =
match xs with
| [] | [_] -> acc
| _::x1::xs' -> loop xs' (x1::acc)
loop l [] |> List.rev
let combinePair l =
let rec loop xs acc =
match xs with
| [] | [_] -> acc
| x0::x1::xs' -> loop xs' ((x0, x1)::acc)
loop l [] |> List.rev
由于我们只是在每次递归调用loop
后返回结果,因此这些函数是尾递归的。
你的功能看起来很不错,但我仍然有几条评论:
match... with
是lec rec
声明后面的几个空格。function
,fun t -> match t with
关键字就可以自然地用于缩短功能。应用上述评论,您的功能如下:
// Remove all even indexed elements from a list and return the rest
let rec removeEven = function
| [] | [_] -> []
| _::x1::xs -> x1::removeEven xs
// Combine list members into pairs
let rec combinePair = function
| [] | [_] -> []
| x0::x1::xs -> (x0, x1)::combinePair xs
答案 1 :(得分:2)
如果你需要一种使用更多内存的速度较慢,维护较少的方法,你可以使用延续。
let removeEven items =
let rec loop f = function
| _::h::t -> loop (fun acc -> f (h::acc)) t
| [] | [_] -> f []
loop id items
但是,嘿,这是尾递归。