I have this factorial predicate.
fact(0, 1).
fact(N, F) :- N > 0,
N1 is N-1,
fact(N1, F1),
F is F1 * N.
How do I change this predicate such that every time a query is issued, the result of the calculation is stored in the database? New queries should use then the stored results if available.
What you are looking for is generally called memoization, but is referred to as tabling in the context of Prolog. Conveniently, there is a library for this called tabling for SWI Prolog.
:- use_module(library(tabling)).
:- table fact/2.
fact(0, 1).
fact(N, F) :- N > 0,
N1 is N-1,
fact(N1, F1),
F is F1 * N.
You can verify that the memoization works by running trace
before your calls to fact
. Note that the two :-
lines are called directives and are run by the compiler, so running them in a repl will not work.
If you don't want to use the tabling library, you can accomplish this with asserta. This will insert a fact at the top of the database, as if you had entered it into the file yourself.
fact(0, 1).
fact(N, F) :-
N > 0,
N1 is N-1,
fact(N1, F1),
F is F1 * N,
asserta(fact(N, F)).
Prolog will see the new predicate first and will use it instead of recomputing your factorial. Once again, you can check this by tracing.