繼前面理解了CPS后,尾遞歸的概念深化了我對(duì)函數(shù)式編程的理解。那Python作為一個(gè)不那么正宗的函數(shù)式語言。
自己能對(duì)尾遞歸優(yōu)化么?我們來看個(gè)例子。
def fib(count, cur=0, next_=1):
if count <= 1:
return cur
else:
# Notice that this is the tail-recursive version
# of fib.
return fib(count-1, next_, cur + next_)
print fib(996)
#執(zhí)行結(jié)果
RuntimeError: maximum recursion depth exceeded
>>>
看來就算我們的函數(shù)已經(jīng)是尾遞歸形式了,堆棧還是會(huì)層層累計(jì),996次就崩潰了。
再來看這個(gè)版本
def fib(count, cur=0, next_=1):
if count <= 1:
yield cur
else:
# Notice that this is the tail-recursive version
# of fib.
yield fib(count-1, next_, cur + next_)
print fib(996)
這樣我們用關(guān)鍵字Yield代替Return把原來的函數(shù)變成了生成器。這樣如果你只傳入?yún)?shù)解釋器是不會(huì)真正運(yùn)行的!!!
#執(zhí)行結(jié)果
<generator object fib at 0x02B00D00>
那我們?cè)趺崔k呢,這里我們使用的技術(shù)稱為Trampline,我們用一個(gè)方法讓它不斷執(zhí)行生成器的next(),達(dá)到我們的目的。
import types
def tramp(gen, *args, **kwargs):
g = gen(*args, **kwargs)
while isinstance(g, types.GeneratorType):
g=g.next()
return g
print tramp(fib, 996)
#執(zhí)行結(jié)果
3919377061614427623668052985592742430389065042819420493170692719480242247392252775480208752179017313071371501566248877239254299341332131655760767122899079117071192049598939666199865808814650408864891823186505
成功了,堆棧不會(huì)溢出了,尾遞歸被真的優(yōu)化了!