% File : INVOCA.PL % Author : Lawrence % Updated: 20 July 1983 % Purpose: Fancy control structures ("invocation" routines). % Most of these predicates are best forgotten. % The exceptions are &/2, forall/2, once/1, not/1. %%% Run this module interpreted %%% INVOCA requires no other modules :- public % /--- begin junk (\\)/2, % | a\\b = once((a;b)) nobt/1, % | nobt(X) = once(X) (thnot)/1, % | thnot(X) = not(X) = \+ X any/1, % | any([G1,...,Gn]) = G1;...;Gn binding/2, % | nobody knows for/2, % | for(N,G) = G,...,G (with N Gs) findall/3, % \--- end junk (&)/2, forall/2, once/1, (not)/1. &(A, B) :- call(A), call(B). \\(A, B) :- (call(A) ; call(B)), !. any([]) :- !, fail. % catch lists with unbound tails any([Goal|Goals]) :- call(Goal). any([_|Goals]) :- any(Goals). binding(N, Goal) :- asserta('\$bind'(N)), N > 0, call(Goal), '\$retr'(N2), N3 is N2-1, ( N3 =< 0 ; asserta('\$bind'(N3)), fail ), !. binding(_, _) :- '\$retr'(_), fail. '\$retr'(N) :- retract('\$bind'(N)), !. % Findall Xs such that P. This is a funny version % which finds the FIRST solution that bagof would % find, but returns the empty list if there are no % solutions. (Logically dubious.) A better version % of this is available elsewhere. findall(X, P, List) :- bagof(X, P, List), !. findall(X, P, []). for(0, Goal) :- !. for(N, Goal) :- N > 0, call(Goal), M is N-1, for(M, Goal), !. % this cuts Goal as well forall(Generator, Test) :- Generator, \+ Test, !, fail. forall(_, _). once(Goal) :- call(Goal), !. nobt(Goal) :- call(Goal), !. not(Goal) :- call(Goal), !, fail. not(Goal). thnot(Goal) :- call(Goal), !, fail. thnot(Goal).