F#学习:尾递归优化

拿简单的阶乘函数来举例,非递归版本可以简单的写成这样:

// 非尾递归
let rec fact n =
    match n with
        | 0 -> 1
        | _ -> n * fact (n - 1)

printfn "%d" (fact 10)

这个会被编译为:

public static int fact(int n)
{
    switch (n)
    {
        case 0:
            return 1;
    }
    return (n * fact(n - 1));
}

而将一个普通递归算法改成成尾递归的关键往往是,在参数列表中多加一个状态参数,这样在调用下一次递归的时候,本次调用时的信息就不需要保存了,避免了 StackOverflowException. F# 可以对尾递归自动做编译优化,变成循环来处理(不确定是否对所有尾递归都能做到?):

// 尾递归优化的版本
let fact2 n =
    let rec loop i result =
        match i with
            | 0 -> result
            | _ -> loop (i - 1) (result * i)
    loop n 1

printfn "%d" (fact2 10) 

这个版本的代码会被编译为:
public static int fact2(int n)
{
    return loop@23(n, 1);
}

internal static int loop@23(int i, int result)
{
    while (true)
    {
        switch (i)
        {
            case 0:
                return result;
        }
        result *= i;
        i--;
    }
}

很明显可以看到代码的结构从递归自动被优化成了一个循环。

原文地址:https://www.cnblogs.com/RChen/p/1786748.html