/* This file defines three useful predicates: retractall(X) which retracts all clauses beginning with X, e.g. retractall(fry(_)) will retract the clause fry(fish) and the clause fry(X) :- (fishy(X);vegatable(X)). scons(File) which consults the file File, but doesn't print extra information on your terminal (scons = Silent CONSult) srecons(File) which does the same but reconsults (srecons = Silent RECONSult) */ retractall(X) :- retract(X), fail. retractall(X) :- retract((X:-Y)), fail. retractall(_). % this succeeds when the other two have failed % because nothing is left to retract. scons(File) :- seeing(Input), see(File), repeat, read(Term), massage(Term), seen, see(Input), !. massage('end_of_file') :- !. massage((?- Term)) :- !, call(Term), !, fail. massage(Term) :- assertz(Term), !, fail. % cut not really needed. srecons(File) :- retractall(retrdone(_)), seeing(Input), see(File), repeat, read(Term), srecons_proc(Term), seen, see(Input), !. srecons_proc('end_of_file') :- !. srecons_proc((?- Term)) :- !, call(Term), !, fail. srecons_proc(Term) :- head(Term,Head), % gets head of Term record_retrdone(Head), % note all previous versions % have been retracted. assertz(Term), fail. record_retrdone(Head) :- retrdone(Head), !. % i.e. done retract before... record_retrdone(Head) :- functor(Head,Func,N), functor(Proc,Func,N), % this makes Proc most general asserta(retrdone(Proc)), retractall(Proc), !. head((A:-B),A) :- !. head(A,A). /* In the above definitions, note that both srecons_proc(_) and massage(_) are defined so as to succeed ONLY when end_of_file is reached; otherwise they do something and fail, thus causing the system to backtrack to a call of read(Term), which fails, and back to repeat, which then succeeds again and leads to another call of read(Term) - which reads the NEXT term, and so on! Note that scons and srecons are very similar. The main difference is that when reconsulting, it is necessary to retract all instances of a clause with head Head when a term with head Head is first encountered, but not at second or subsequent encounters. The purpose of retrdone(_) is to exist when the first time retraction has been done, so ensuring that retraction happens ONLY ONCE This program is also in Clocksin and Mellish "Programming in Prolog". */