iT邦幫忙

2025 iThome 鐵人賽

DAY 30
0
Software Development

通勤看手機就可讀懂的 Elixir 語言入門教學系列 第 30

尾遞迴最佳化 (Tail Call Optimization)

  • 分享至 

  • xImage
  •  

假如我們要一個一個計算 1 到指定數字的加總
例如 1 到 3 為 1 + 2 + 3 = 6

(為了示範尾遞迴,先別用梯形公式)

def sum(0), do: 0
def sum(n) do
  n + sum(n - 1)
end

這樣可以得到結果,但是這個作法沒有尾遞迴
這個執行的結果為

5 + sum(5 - 1)
5 + 4 + sum(4 - 1)
5 + 4 + 3 + sum(3 - 1)
5 + 4 + 3 + 2 + sum(2 -1)
5 + 4 + 3 + 2 + 1
15

這種寫法如果要計算的量非常大的話,會佔非常多的記憶體空間 (stack)

訣竅為,最後一個呼叫的函式為自己

通常可以透過把 accumulator 加入參數內一起傳送來反過來

def sum(n), do: sum(n, 0)

def sum(0, acc), do: acc
def sum(n, acc) do
  sum(n - 1, acc + n) # 最後呼叫的是自己
end

執行的結果就變成

sum(5)
sum(5, 0)
sum(4, 5)
sum(3, 9)
sum(2, 12)
sum(1, 14)
sum(0, 15)
15

可以使用同一個 stack

如果使用 Enum.map, Enum.reduce 等內建的函式,就一定會是尾遞迴優化


上一篇
關於遞迴 (Recursion)
系列文
通勤看手機就可讀懂的 Elixir 語言入門教學30
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言