翻了一下list模塊,看的時候,突然發現,尾遞歸其實是很容易展開成循環的。
想起讀書時剛開始學程序,C語言,一直再糾結的一個問題,就是如何讓一個函數返回兩個參數的結果,哈哈,不要笑我。
do_sth([], [], SA, SB)->{SA, SB};
do_sth([HA|TA]=LA,[HB|TB]=LB, SA, SB)->
do_sth(TA, TB, HA+SA,HB+SB).
用erlang隨便寫了一個尾遞歸的函數,實現了對列表的一種計算
struct{int sa, int sb} do_sth(vector<int>:::iterator la, vector<int>::iterator lb, int sa, int sb){
if(...){
do_sth(....)
}else{struct{sa, sb}};
}
翻譯成C++大概就是這個樣子,代碼寫的很醜= =。
我覺得看尾遞歸代碼的時候,就當他是循環,就很容易看了,終止條件就是else,其它就計算完後重新執行自己這個函數。
寫尾遞歸也是這個思路,else上面的代碼就把事情做完,else下面的代碼就只做最後的清理,整理一下就是尾遞歸了。。
我覺得尾遞歸有一個特點,就是把中間值傳到下一層遞歸裏面去了,就是第三第四個參數,
一般C++寫的遞歸是把中間值返回到上一層調用,然後繼續計算,然後再把結果返回上一層調用。
這種區別就使得一般的C++代碼一定要有個調用棧才能保證程序的正確性,如果把本層的計算結果傳入到下一層進行計算,那麼這個調用棧就不需要了,
就像完成了一次goto的過程。
即尾遞歸的計算順序與遞歸是相反的。