# [mercury-users] Getting all facts of a predicate [was: Still compiling ...]

Ralph Becket rafe at cs.mu.OZ.AU
Mon Feb 24 10:53:15 AEDT 2003

```The compiler really slows down on large static structures; I believe
some of the analyses it performs are quadratic in the number of
variables in a clause or definition.  Long lists are a classic case: the
unification

Xs = [1, 2, 3, 4, 5, ..., 1000]

for instance is first expanded into

Xs     = [1 | Xs1],
Xs1    = [2 | Xs2],
Xs2    = [3 | Xs3],
...
Xs999  = [1000 | Xs1000],
Xs1000 = []

and all this has to be type checked and so forth.

For your case, if the data is static then you can do something like
this:

:- func all_p_pairs = list({int, int}).

all_p_pairs = solutions(enumerate_p).

:- pred enumerate_p({int, int}).
:- mode enumerate_p(out) is multi.

enumerate_p({X, Y}) :-
p(X, Y).

:- pred p(int, int).
:- mode p(in,  out) is semidet.
:- mode p(out, out) is multi.

p(0, 0).
p(1, 1).
p(2, 4).
... and so on ...
p(999, 998001).

If you need access to the list of results relatively frequently, you
can memo the results by adding the declaration

:- pragma memo(all_p_pairs/0).

Now the call to solutions will only happen the first time all_p_pairs/0
is evaluated.  Calls to all_p_pairs/0 thereafter will simply retrieve
the previously computed result.

For p/2, provided its arguments are only some combination of strings,
ints and floats, you can use a fact table for possibly greater
efficiency.  You do this by putting the definitions for p/2 into a file,

:- pragma fact_table(p/2, "p.fact_table").

in place of the definitions in the main source file.

If your data is not static, you may well want to use the hash_table
library module which provides for very fast data retrieval.

Ralph
--------------------------------------------------------------------------
mercury-users mailing list
post:  mercury-users at cs.mu.oz.au