不,您使用Acc
不會使其尾遞歸。如果您的分支返回[H| remove(T, Key, Acc)]
這不是尾巴呼叫,並且此分支將在大部分時間使用。更確切地說,您使用Acc
是無用的,因爲它將是整個時間的[]
,您根本不會改變它的值。正確的代碼應該看起來像。
delete(Key, Database) ->
remove(Database, Key, []).
remove([], Key, Acc) ->
lists:reverse(Acc);
remove([H|T], Key, Acc) ->
if
element(1, H) /= Key ->
remove(T, Key, [H|Acc]);
true ->
remove(T, Key, Acc)
end.
但如果你的列表成員總是對我寧願直接模式匹配:
delete(Key, Database) ->
remove(Database, Key, []).
remove([], Key, Acc) ->
lists:reverse(Acc);
remove([{Key, _}|T], Key, Acc) ->
remove(T, Key, Acc);
% if it should delete only first occurrence then lists:reverse(Acc, T);
remove([H|T], Key, Acc) ->
remove(T, Key, [H|Acc]).
但我認爲這是例子可以申請Myth: Tail-recursive functions are MUCH faster than recursive functions所以我會用更簡單的遞歸版本:
delete(Key, []) -> [];
delete(Key, [{Key, _}|T]) -> delete(Key, T);
% if it should delete only first occurrence then just T;
delete(Key, [H|T]) -> [H | delete(Key, T)].
如果你想知道是否是尾遞歸,是否有什麼需要返回函數返回前的調用值。在這種情況下,cons正在等待結果,所以不,它不是尾遞歸。 – Dustin 2010-04-17 22:14:31
這是我在這裏回答你的問題的一個的改寫:http://stackoverflow.com/questions/2658631/tail-recursion-in-erlang/2658766#2658766 – 2010-04-18 06:15:03
@Jeremy這是不是一個完整的改寫,因爲我期待有關if語句指導,但我拿點,不會再發布關於這一主題。 – dagda1 2010-04-18 10:03:57