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