zoukankan      html  css  js  c++  java
  • 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--;
        }
    }

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

  • 相关阅读:
    bzoj2287 [POJ Challenge]消失之物
    bzoj4504 K个串
    Tjoi2016&Heoi2016 字符串
    bzoj2555 SubString
    WC2017 游记
    《大灌篮》观后感
    Codeforces Round #394 (Div. 2)
    bzoj3489 A simple rmq problem
    Goodbye Bingshen
    COGS2216 你猜是不是KMP
  • 原文地址:https://www.cnblogs.com/RChen/p/1786748.html
Copyright © 2011-2022 走看看