That is correct – only one node is created. Although append/3
won’t be expensive in that situation either: append([Item], OldList, NewList)
becomes NewList = [Item|OldList]
.
And when your computation is finished, you can use reverse/2
to put the list in insertion order, if that’s what you want.
append(OldList, [Item], NewList)
will create N new nodes when creating NewList
from OldList
(but the contents of the nodes won’t be copied).
put_assoc(Key, OldAssoc, Value, NewAssoc)
or rb_insert(OldTree, Key, Value, NewTree)
will create O(log N) new nodes.
Note that the typical Prolog idiom of generating a new list from an old one, is an O(N) algorithm; but if you use append/3
it becomes O(N). The following code illustrates some of the options (I haven’t tested any of this, so there could be typos):
% O(N) algorithm:
transform([], []).
transform([X|Xs], [Y|Ys]) :-
pred(X, Y),
transform(Xs, Ys).
% O(N):
transform(Xs, Ys) :- maplist(pred, Xs, Ys).
% O(N^2) algorithm:
transform(Xs, Ys) :- transform(Xs, [], Ys).
transform([], Result, Result).
transform([X|Xs], SoFar, Ys) :-
pred(X, Y),
append(SoFar, [X], SoFar2),
transform(Xs, SoFar2, Ys).
% O(N) algorithm:
transform(Xs, Ys) :-
transform(Xs, [], YsReverse),
reverse(YsReverse, Ys).
transform([], Result, Result).
transform([X|Xs], SoFar, Ys) :-
pred(X, Y),
transform(Xs, [Y|SoFar, Ys).
% O(N) algorithm:
transform(Xs, Ys) :- phrase(transform(Xs), Ys).
transform([]) --> [].
transform([X|Xs]) -->
{ pred(X, Y) },
[Y],
transform(Xs).
% O(M + log N) algorithm for K-V pairs (see also `map_assoc/3):
transform([], Assoc, Assoc).
transform([K|Ks], Assoc0, Assoc) :-
get_assoc(K, Assoc0, V0)
pred(K, V0, V1),
put_assoc(K, Assoc0, V1, Assoc1),
transform(KVs, Assoc1, Assoc).