如何使这些简单的函数在f#中递归递归

我有这两个功能

//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#newbie :))

任何其他有关我的代码的建设性评论当然是最受欢迎的!


在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 ,这些功能是尾递归。

你的功能看起来不错,但我仍然有几个意见:

  • 缩进在F#中很重要。 我宁愿match... with lec rec宣言后面的几个空格。
  • Patter匹配案例应遵循一致的顺序。 首先从基本案例开始,这是一个好主意。
  • 当你有一个fun t -> match t with的模式fun t -> match t with时, function关键字很自然地用于缩短函数。
  • 最好摆脱不必要的括号,特别是在有一个参数的函数中。
  • 应用上面的评论,你的功能如下:

    // 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
    

    如果您需要更慢,维护更少的方法来使用更多内存,则可以使用延续。

    let removeEven items = 
      let rec loop f = function
        | _::h::t -> loop (fun acc -> f (h::acc)) t
        | [] | [_] -> f []
      loop id items
    

    但是,嘿,它是尾递归的。

    链接地址: http://www.djcxy.com/p/14143.html

    上一篇: how to make these simple functions tail recursive in f#

    下一篇: How can a time function exist in functional programming?