:- non_counted_backtracking staggered_if_then/2.
staggered_if_then(G1, G2) :-
- '$get_staggered_cp'(B),
call(G1),
- '$set_cp'(B),
+ !,
call(G2).
+%% ;(G1, G2)
+%
+% Disjunction (or)
G1 ; G2 :- control_entry_point((G1 ; G2)).
:- non_counted_backtracking staggered_sc/2.
- staggered_sc(G, _) :- call(G).
+ staggered_sc(G, _) :-
+ ( nonvar(G),
+ G = '$call'(builtins:staggered_if_then(G1, G2)) ->
+ call(G1),
+ !,
+ call(G2)
+ ; call(G)
+ ).
staggered_sc(_, G) :- call(G).
+%% !.
+%
+% Cut operator. Discards the choicepoints created since entering the prediacate in which the operator appears.
+% Using cut is not recommended as it introduces a non-declarative flow of programming and makes it more difficult
+% to reason about the programs. Also restricts the ability to run the program with alternative execution strategies
!.
:- non_counted_backtracking set_cp/1.
set_cp(B) :- '$set_cp'(B).
+%% ,(G1, G2)
+%
+% Conjuction (and)
','(G1, G2) :- control_entry_point((G1, G2)).
+
:- non_counted_backtracking control_entry_point/1.
control_entry_point(G) :-
:- non_counted_backtracking bagof/3.
+%% bagof(Template, Goal, Solution).
+%
+% Unify Solution with a list of alternatives of the variables in Template coming from calling Goal.
+% If Goal has no solutions, the predicate fails.
+% If free variables that are not in Template appear in Goal, the predicate will backtrack over
+% the alternatives of those free variables. However, you can use the syntax `Var^Goal` to not bind
+% Var in Goal and prevent that.
+%
+% Example:
+%
+% f(1, 3).
+% f(2, 4).
+% ?- bagof(X, f(X, Y), Bag).
+% Y = 3, Bag = [1],
+% ; Y = 4, Bag = [2].
+% ?- bagof(X, Y^f(X, Y), Bag).
+% Bag = [1,2].
bagof(Template, Goal, Solution) :-
error:can_be(list, Solution),
- term_variables(Template, TemplateVars0),
- term_variables(Goal, GoalVars0),
- sort(TemplateVars0, TemplateVars),
- sort(GoalVars0, GoalVars),
- set_difference(GoalVars, TemplateVars, Witnesses0),
+ term_variables(Template, TemplateVars),
+ term_variables(Goal, GoalVars),
+ term_variables(TemplateVars+GoalVars, TGVs),
+ lists:append(TemplateVars, Witnesses0, TGVs),
findall_with_existential(Template, Goal, PairedSolutions0, Witnesses0, Witnesses),
keysort(PairedSolutions0, PairedSolutions),
group_by_variants(PairedSolutions, GroupedSolutions),
:- non_counted_backtracking setof/3.
+%% setof(Template, Goal, Solution).
+%
+% Similar to bagof/3 but Solution is sorted and duplicates are removed. Example:
+%
+% f(1, 2).
+% f(1, 3).
+% f(2, 4).
+% ?- setof(X, Y^f(X, Y), Set).
+% Set = [1, 2].
setof(Template, Goal, Solution) :-
error:can_be(list, Solution),
- term_variables(Template, TemplateVars0),
- term_variables(Goal, GoalVars0),
- sort(TemplateVars0, TemplateVars),
- sort(GoalVars0, GoalVars),
- set_difference(GoalVars, TemplateVars, Witnesses0),
+ term_variables(Template, TemplateVars),
+ term_variables(Goal, GoalVars),
+ term_variables(TemplateVars+GoalVars, TGVs),
+ lists:append(TemplateVars, Witnesses0, TGVs),
findall_with_existential(Template, Goal, PairedSolutions0, Witnesses0, Witnesses),
keysort(PairedSolutions0, PairedSolutions),
group_by_variants(PairedSolutions, GroupedSolutions),