[英]Does every Haskell function do tail calls?
我想知道Haskell中的每個函數都應該是尾遞歸的。
階乘函數實現為非尾遞歸函數:
fact 0 = 1
fact n = n * fact (n - 1)
每個運算符也是一個函數,所以這等效於
fact 0 = 1
fact n = (*) n (fact (n - 1))
但這顯然是我的尾聲。 我想知道如果每個調用都只是在堆上創建一個新的thunk,那么這段代碼為什么會導致堆棧溢出。 我不應該堆溢出嗎?
在代碼中
fact 0 = 1
fact n = (*) n (fact (n - 1))
如您所見,最后一個(*) ...
是尾部調用。 但是,最后一個實參fact (n-1)
將產生一個thunk,緊接着(*)
要求它。 這導致對fact
的無尾的呼吁。 遞歸地,這將消耗堆棧。
TL; DR:發布的代碼執行尾部調用,但(*)
則不執行。
(此外,Haskell中的“堆棧”概念並不像嚴格的語言中那么清晰。Haskell的某些實現使用的東西要比這復雜得多。如果需要一些詳細信息,可以搜索“推入/輸入vs評估/應用”策略。 。)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.