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.
Edit
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.