I have introduced meta predicates fold/3
, fold/4
, fold/5
.
Although they are byproduct caused by my big misunderstanding issues on foreach
discussed on a thread else, these three are what I wanted have since earlier. I borrowed the name fold
because it is a generalized foldl/4
for me. They are all small and clear, and prefixed sample queries are enough for the reader, I hope. In fact, I guess the reader already uses similar ones in his private use. I will be glad if they would be shared with others. Also I would like to see such private handy tools of others for their daily use.
EDIT:
Since about 10 years ago I had meta predicates for repeating
action, though they were always in a messy state, because without that it is easy for us to write simple repeating action in Prolog like
between(1, 5, I), writeln(I), fail; true
Remembering the traditional idea of Prolog of “backtracking as a generalized recursion,” now I have changed my mind so that I should cleanup my messy meta predicates for repeating (recursion) in stead of introducing similar predicates.
In addition, to be honest I don’t know the background of the name “fold”. I think it came from mathematics, but but as far as I know they seem different from repeating action. It may not be appropriate to give name “fold” to repeating action like the above example.
End of EDIT.
% ?- N is 10^8, time(fold(I, between(1, N, I), is(C, 1+2))).
% ?- fold(M, member(M, [1,2,3]), cons, [], X).
%@ X = [3, 2, 1].
cons(X, Y, [X|Y]).
:- meta_predicate fold(?, :, :, ?, ?).
fold(V, G, A, X, Y):- Acc = '$ACC'(X),
( call(G),
arg(1, Acc, U),
call(A, V, U, W),
nb_setarg(1, Acc, W),
fail
; arg(1, Acc, Y)
).
% ?- Sum = acc(0), fold(J, between(1, 3, J), test_add_to_acc, Sum).
%@ Sum = acc(6).
test_add_to_acc(X, Acc):- arg(1, Acc, V),
V0 is X + V,
nb_setarg(1, Acc, V0).
:- meta_predicate fold(?, :, :, ?).
fold(V, G, A, X):-
call(G),
call(A, V, X),
fail.
fold(_, _, _, _).
% ?- fold(I, between(1, 3, I), writeln).
%@ 1
%@ 2
%@ 3
%@ true.
% ?- fold(I, between(1, 3, I), X^(Y is X*X, writeln(Y))).
%@ 1
%@ 4
%@ 9
%@ I = X.
:- meta_predicate fold(?, :, :).
fold(V, G, V^A):-!,
( call(G),
call(A),
fail
; true
).
fold(V, G, A):-
( call(G),
call(A, V),
fail
; true
).