`fold/3`, `fold/4`, `fold/5` as members of a family of `foldl/4`

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
	).
1 Like