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--;
}
}
很明显可以看到代码的结构从递归自动被优化成了一个循环。
浙公网安备 33010602011771号