如何改进这个F#功能

Rya*_*yan 4 f# functional-programming

我在C#方面很有经验,但对F#和功能编程很新.现在我想在F#中实现一个类库.这是其中一个函数:它取一个整数列表<= 9并改变连续9,如9,9,9,9到9,10,11,12.例如[9; 9; 9; 1; 4; 0; 1; 9; 9; 9; 9]将改为[9; 10; 11; 1; 4; 0; 1; 9; 10; 11; 12.

C#功能很简单:

void ReleaseCap(List<int> items)
{
    for (int i = 1; i < items.Count; i++)
    {
        var current = items[i];
        var previous = items[i - 1];
        //If curernt value = 9 and previous >=9, then current value should be previous+1
        if (current == 9 && previous >= 9)
        {
            items[i] = previous + 1;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

现在是我的F#尾递归.它不是通过索引循环List,而是递归地将项目从初始列表移动到已处理的列表,直到初始列表中的所有内容都消失为止:

let releaseCap items =
    let rec loop processed remaining = //tail recursion
        match remaining with
        | [] -> processed //if nothing left, the job is done.
        | current :: rest when current = 9 -> //if current item =9
            match processed with
            // previous value >= 9, then append previous+1 to the processed list
            | previous :: _ when previous >= 9 -> loop (previous+1 :: processed) rest 
            //if previous < 9, the current one should be just 9
            | _ -> loop (current :: processed) rest 
        //otherwise, just put the current value to the processed list
        | current :: rest -> loop (current :: processed) rest 
    loop [] items |> List.rev
Run Code Online (Sandbox Code Playgroud)

虽然C#版本是微不足道和直观的,但F#代码很冗长而且不那么直观.是否可以改进F#代码的任何部分以使其更优雅?

Gus*_*Gus 5

您可以重用现有函数以简化代码.通常,当您更改列表中的项目时,您会想到一个map但是在这种情况下,您需要记住以前计算中应该为每个项目传递的内容,因此您应该针对fold相关函数.

这是一个: List.scan

let releaseCap items =
    items
        |> List.scan (fun previous current -> 
            if current = 9 && previous >= 9 then previous + 1
            else current) 0  
        |> List.tail
Run Code Online (Sandbox Code Playgroud)

FP不只是使用递归而不是循环.递归通常用于基本和可重用的函数,然后通过组合这些函数,您可以解决复杂的问题.

注意:您正在将C#解决方案与F#解决方案进行比较,但是您是否注意到除了语言之外,两种解决方案之间存在重要差异?您的C#解决方案使用可变性.

  • 对于OP:[FSharp.Collections](https://msdn.microsoft.com/en-us/library/ee353413.aspx)文档在了解预先存在的内容是什么的情况下非常有用.那里操纵本机集合. (3认同)