尾呼叫及其消除

2021-10-25 07:33:04 字數 938 閱讀 9576

概念:乙個函式裡的最後乙個動作是乙個函式呼叫的情形

lua例:

function

func1

(x)do

return

func2

(x)end

也就是說,是這個呼叫的返回值直接被當前函式返回的情形。

為什麼這種情況要單獨拿出來定義,首先要明確函式呼叫棧的概念。

呼叫棧在程式的記憶體空間中,有一塊專門的區域被用來記錄正在呼叫的函式的情況,這塊區域就是函式呼叫棧。

每次呼叫乙個新的函式時,就會在呼叫棧頂進行乙個壓棧操作;函式執行完畢時,會執行彈棧操作,清除被呼叫函式的資源。

尾遞迴尾呼叫的函式是當前函式自身,這種情況被成為尾遞迴。

如果在函式內呼叫函式的話,就會導致不斷壓棧而沒有彈棧的情況,其結果是消耗大量記憶體並且有撐爆函式呼叫棧空間的風險,尤其是遞迴的情況下。

但尾呼叫有所不同,普通函式內呼叫函式,因為後續還有要執行的語句,所以無法優化。而尾呼叫由於是函式的最後一條語句,優化是可以實現的,尤其是尾遞迴的情況下,優化可以提高不少效率。

主要目的:使程式設計師可以使用遞迴代替迴圈且不損失效能。

呼叫棧執行機制:呼叫棧在將乙個函式壓棧時,會記住他的返回位置,當乙個函式呼叫結束時,他的返回值會被放到棧中所記錄的返回位置上。舉例來說,函式a在第三條語句時呼叫函式b,那麼函式b被壓棧,它的返回位置就是函式a呼叫它的地方,當函式b執行結束,它的返回值就會被放到a呼叫函式b的位置,之後再執行下面的語句。

消除實現:對於尾呼叫而言,被調函式的位置可以不用記錄在呼叫棧中。用上述例子模擬,如果a在return語句呼叫函式b,那麼b的呼叫和返回位置就是a的返回位置。所以尾呼叫消除就是在不改變當前呼叫棧的呼叫情況下,直接跳轉進入另乙個函式的呼叫,並且該函式的返回位置就是呼叫該函式函式的返回位置。這樣一來,就省下了一次壓棧和一次彈棧的消耗。

尾呼叫尾遞迴及其優化(筆記)

尾呼叫 尾呼叫 tail call 是函式式程式設計的乙個重要概念,本身非常簡單,即指某個函式的最後一步呼叫另乙個函式。function f x 上述 中,函式的最後一步是呼叫函式g,這就叫尾呼叫。以下三種情況,都不屬於尾呼叫。function f x function f x function f...

尾呼叫 尾遞迴

首先什麼是尾呼叫呢?我的理解是在,函式的最後呼叫乙個函式,並不包含該函式的任何變數。如 def f n return g n 複製 這個就是尾呼叫,尾呼叫的乙個好處就是,不用生成呼叫棧,因為假設是個尾呼叫,那麼當我執行到函式末尾的時候,這個函式相關的資訊我都可以不用保留了,因此不會出現棧溢位的問題。...

尾呼叫和尾遞迴

造成這樣的結果是因為每個函式在呼叫另乙個函式的時候,沒有return該呼叫,所以執行引擎會認為你還沒有呼叫完畢,會保留呼叫幀。而如果使用尾呼叫優化,呼叫幀就永遠只有一條,這個時候就會節省很大一部分的記憶體空間,維護了 執行的流暢性。以上 就叫做尾呼叫優化,這個時候呼叫幀就永遠只有一條,節省了部分記憶...