iT邦幫忙

2025 iThome 鐵人賽

DAY 30
1
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) }}
直播中

1 則留言

2
taiansu
iT邦新手 2 級 ‧ 2025-10-14 18:22:30

來恭喜一下 XD

我要留言

立即登入留言