我正在通過「Learn Prolog now」在線書籍尋找樂趣。我應該避免使用Prolog和一般的尾遞歸嗎?
我想寫一個謂詞,通過列表的每個成員,並添加一個到它,使用累加器。我已經很容易地做到了,而且沒有尾遞歸。
addone([],[]).
addone([X|Xs],[Y|Ys]) :- Y is X+1, addone(Xs,Ys).
但我已經讀過,出於性能原因最好避免這種類型的遞歸。這是真的?總是使用尾遞歸是否被認爲是「良好實踐」?使用累加器來養成良好習慣是否值得努力?
我試圖將此示例更改爲使用累加器,但它顛倒了列表。我怎樣才能避免這種情況?
accAddOne([X|Xs],Acc,Result) :- Xnew is X+1, accAddOne(Xs,[Xnew|Acc],Result).
accAddOne([],A,A).
addone(List,Result) :- accAddOne(List,[],Result).
' addone'已經完全可以通過尾巴優化。它是[tail遞歸*「modulo cons」*](https://en.wikipedia.org/wiki/Tail_call#Tail_recursion_modulo_cons),並且Prolog確實有這種優化 - 新的單元格[Y | Ys]是分配* first *與其中的兩個「洞」(兩個尚未實例化的logvars,'Y'和'Ys'),然後'Y'在規則體內實例化(通過'is/2'),然後* *遞歸調用實例化邏輯變量'Ys'。因此不需要從遞歸調用返回到這個規則的主體。 –
LPN!現在通過實例展示了不同之處。就我所知,Prolog是尾部遞歸優化的,因此它是可取的,因爲它通過不退後有效地將N步變爲N/2。 LPN:http://www.learnprolognow.org/lpnpage.php?pagetype=html&pageid=lpn-htmlse20第5.3章,2018年1月。 –