• Python尾递归-创始人为何不愿TRE以及我们如何模拟TRE


    TRE=Tail Recursion Elimination

    创始人是不愿意实现TRE的.他专门用了一篇文章来阐述原因.

    http://neopythonic.blogspot.com/2009/04/tail-recursion-elimination.html

    1.不利于查BUG.

    2.现有的1000递归深度够用.

    3.递归不是所有编程的基础,也不是一个日常工具.

    4.他举了个例子说明第四点,大概是指Python动态的特性不适合递归:

    def f(x):
        print 'original'
        if x > 0:
            return f(x-1)
        return 0
    g = f
    def f(x):
        print 'new'
        return x
    print g(5)

    最终结果是4:

    original
    new
    4

    最后总结:

    After all TRE only addresses recursion that can easily be replaced by a loop.

    意思应该是说所有真正需要TRE的地方都能轻松改写为循环.

    看来我是不能指望Python语言支持TRE了.

    但还是有很多顽强的程序员用各种方法变相支持TRE.比如下面这位还用装饰器的形式实现了.

    http://web.mit.edu/kmill/www/programming/tailcall.html

    class TailCaller(object) :
        def __init__(self, f) :
            self.f = f
        def __call__(self, *args, **kwargs) :
            ret = self.f(*args, **kwargs)
            while type(ret) is TailCall :
                ret = ret.handle()
            return ret
    
    class TailCall(object) :
        def __init__(self, call, *args, **kwargs) :
            self.call = call
            self.args = args
            self.kwargs = kwargs
        def handle(self) :
            if type(self.call) is TailCaller :
                return self.call.f(*self.args, **self.kwargs)
            else :
                return self.f(*self.args, **self.kwargs)
    
    @TailCaller
    def fact(n, r=1) :
        if n <= 1 :
            return r
        else :
            return TailCall(fact, n-1, n*r)

    print fact(2500)

    最朴素的形式是:

    def TCO(f):    
        def inner(*nkw,**kw):
            result=f(*nkw,**kw)
            while callable(result):
                result=result()
            return result
        return inner
            
    def fab(n,s=1):
        if n<2:
            return s
        else:
            return lambda :fab(n-1,s*n)
    
    tcoFab=TCO(fab)
    print tcoFab(2500)

    这个更容易理解,性能也应该会更好,只是行文略显复杂了一点点.主要是由于Python运行时的动态特性,你不能使用更酷的装饰器形式fab=TCO(fab).

    我个人是比较支持这种朴素形式的.

    网上还有其他一些什么抛出异常法之类的,用到了sys模块,太复杂了,看不懂,故不用.

  • 相关阅读:
    去中心化存储的QoS是什么?
    谈如何真正地做好去中心存储?
    Kowala协议:一组分布式,自我调节,资产跟踪特性的加密货币(二)
    MySQL主从备份
    Java面试总结-基础篇2
    Java面试总结-基础篇1
    锁定网络问题的方法
    我是如何在实际项目中解决MySQL性能问题
    serialVersionUID的作用
    Windows和Linux下如何自动备份MySQL
  • 原文地址:https://www.cnblogs.com/xiangnan/p/3407780.html
Copyright © 2020-2023  润新知