Did you know ... Search Documentation:
Pack memo -- README

This package provides library(memo), a tool for memoising deterministic predicates in memory or persistently on the file system. It also includes library(typedef), which provides support for defining algebraic data types that hook into the type-checking framework of library(error).

See library(memo) module header for more information.

Quick test

This is a small test file that you can use to check if it works.

:- use_module(library(memo)).
:- use_module(library(typedef)).

:- type maybe(A) ---> nothing; just(A).
:- volatile_memo sqrt1(+float, -maybe(float)).
:- persistent_memo sqrt2( +float, -float).

sqrt1(X,just(Y)) :- X>=0, !, Y is sqrt(X).
sqrt1(_,nothing).

% this will throw an exception if X<0
sqrt2(X,Y) :- Y is sqrt(X).

:- initialization
                db_attach('test.db',[]),  % attach database for persistent memo
                debug(memo).              % tocheck memoisation operations

Then, you can make queries such as

?- sqrt1(16,X).   % leads to type error (16 is not a float)
?- sqrt1(16.0,X). % computes X=4.0
?- sqrt1(16.0,X). % looks up old result, X=4.0
?- sqrt1(-4.0,X). % fails
?- sqrt2(9.0,X).  % computes X=3.0 and stores persistently
?- sqrt2(-4.0,X). % records exception and then rethrow is
?- sqrt2(-4.0,X). % rethrows recorded exception

The debug messages should indicate that repeated computations are being avoided, even for failing goals, like sqrt1(-4.0,X), and computations that throw exceptions, like sqrt2(-4.0,X).

Changes in v0.5

memo/1 and memo/2 are now steadfast with respect to output arguments in the
memoised goal. This means that instead of throwing an exception if an
output argument is nonvar on entry, the computation proceeeds _exactly_ as
if it were unbound, followed by a final semi-deterministic unification.
Any side-effects of calling the memoised computation (ie the memoisation of
the result) goes ahead even if the output arguments do not unify and the
call as a whole fails.

An alternative approach would be to abort the memoisation if the output
values do not unify with those provided on input.

Changes in v0.4

memo/1 now behaves differently if the memoised predicate fails or throws
an exception, in which case the result will now NOT be stored. This is probably
the more useful behaviour on the whole, because failures and exceptions
are more likely to be due to bugs rather than any inherent partiality in the
function being computed.

Changes in v0.3

The library now has a notion of 'current evaluation mode', which applies when
memoised predicates are called directly by their original names. In the previous
version, this resulted in a call to memo/1, i.e., strict mode checking is done,
previously stored computations are checked, and a new computation done if
necessary and the result stored. In v0.3, the current mode can be 'memo',
'browse' or 'compute', which result in calls to memo/1, browse/1 or compute/1
respectively. The initial mode is 'memo', retaining backwards compatibility with
v0.2. The only way to affect the mode is to use call_with_mode(Mode,Goal), which
calls an arbitrary goal in an environment with the evaluation mode set to Mode.
There is no way to globally set the evaluation-mode -- this is an intentional
design decision to ensure that any goal given at the top level ?- prompt always
behaves the same way.

Changes in v0.2