2017-05-24 33 views
-2

我最近了解到尾遞歸作爲一種遞歸方式,當你給它一個太大的數字來處理時,它不會崩潰。我意識到我可以很容易地將一個尾遞歸作爲一個while循環來重寫,並且它基本上完全相同,這導致我想知道 - 當你用普通循環做所有事情時,有沒有用於遞歸?遞歸有什麼用處嗎?

是的,遞歸代碼看起來更小,更容易理解,但它也有可能完全崩潰,而簡單的循環無法崩潰做同樣的任務。

+0

歡迎來到StackOverflow。請閱讀並遵守幫助文檔中的發佈準則。 [在主題](http://stackoverflow.com/help/on-topic)和[如何提問](http://stackoverflow.com/help/how-to-ask)適用於此處。 這個問題在Stack Overflow和Internet上已經有了很多答案。 – Prune

+2

有沒有用於循環?遞歸可以做一切循環都可以。一個簡單的循環會因索引超出範圍或整數溢出而崩潰,但是您知道,程序員不應該爲確保其代碼不會崩潰負責! – MrZander

+0

@Prune我沒有發現他們中的任何一個對我有幫助 – umnikos

回答

0

我要例如Haskell language,它是純功能

在Haskell每個功能是在數學意義上 (即,「純」)的功能。即使是副作用的IO操作也不過是純代碼生成的內容的描述。沒有 語句或指令,只有表達式不能變異 變量(本地或全局),也不像訪問狀態像時間或隨機 號碼。

所以,在Haskell遞歸函數是尾遞歸如果 遞歸調用的最終結果是函數本身的最終結果。如果必須進一步處理遞歸調用的結果(例如,通過向其添加 1或將另一個元素添加到它的開頭),則不是尾遞歸的 。 (see here

另一方面,在許多編程語言中,調用一個函數使用堆棧空間,所以一個尾遞歸函數可以構建一個大堆的自身調用,這會浪費內存。由於在尾調用中,包含函數即將返回,它的環境實際上可以被丟棄,並且遞歸調用可以在不創建新的棧幀的情況下進入。這個技巧被稱爲尾部呼叫消除或尾部呼叫優化,並允許尾部遞歸功能無限期地重複發生。

+0

可能有重複的問題。我目前正在學習lisp,它有標準循環和尾遞歸優化。我試圖找到一個理由,當一個普通的循環完成相同的工作而不聲明函數時使用尾遞歸。 – umnikos

+1

您是否嘗試過使用循環解決河內塔? – Nykros

+0

這是一個夢幻般的例子@Nykros,在很多方面是更簡單的閱讀和理解尾遞歸,有時也更快 –