In Prolog, calls to the builtin predicates
can change the set of clauses of the program currently being executed.
This makes compilation very tricky,
and different Prolog systems react differently
when the program alters the definition of a predicate that has active calls.
It also makes program analysis almost impossible,
since the program that the compiler should analyze
is not actually available at compilation time.
Since Mercury is a compiled language,
it does not allow the compiled program to be altered in any way.
Most uses of
retract in Prolog programs
are not actually intended to alter the program.
Their purpose is just to maintain a set of facts,
with semantically separate sets of facts being stored in separate predicates.
(Most Prolog systems require these predicates
to be marked as
A Mercury programmer who wants to store a set of facts
would simply store those facts as data (not as code) in a data structure.
The standard library contains several abstract data types (ADTs) for storing collections of items, each of which is useful for different classes of problems.
If the order of the items in the collection is important,
list has lower constant factors,
cord ADTs supports concatenation in constant time.
queue ADTs implement
lists with specific semantics and operations appropriate to those semantics.
If the order of items in the collection is not important,
and if the items are key-value pairs,
you can store them in ADTs implementing several different kinds of trees,
In the absence of a compelling reason to choose a different implementation,
we recommend the
map ADT for generic use.
Maps are implemented using 234 trees,
which are guaranteed to be balanced and thus have good worst-case behavior,
but also have good performance in the average case.
specialized version of maps.
If the items in the collection are not key-value pairs,
then consider the
set ADT itself has several versions,
some based on trees and some based on bit vectors,
each with its own tradeoffs.
The Mercury standard library has some modules for more specialized collections as well, such as graphs. And of course, if needed, you can always create your own ADT.
If for some reason you cannot thread variables holding some data through the parts of your program that need access to that data, then you can store that data in a ‘mutable’, which is as close as Mercury comes to Prolog’s dynamic predicates. Each Mercury mutable stores one value, though of course this value can be a collection, and that collection may be (but doesn’t have to be) implemented by one of the Mercury standard library modules listed above.
Each mutable has a getter and setter predicate.
You can set things up so that the getter and setter predicates
both function as I/O operations,
destroying the current state of the world
and returning a new state of the world.
This effectively considers the mutable to be part of the state of the world
outside the Mercury program.
io module also provides another way to do this,
by allowing the storage of information in the
using the predicates
These predicates take an argument of type
univ, the universal type,
so that by using
it is possible to store data of any type in the
Alternatively, you can set things up so that the getter and setter predicates of a mutable are not I/O operations, but in that case calls to those predicates are not considered pure Mercury, and must instead use Mercury’s mechanisms for controlled impurity. These mechanisms require all code that is not pure Mercury to be explicitly marked as such. They are intended to allow programmers to implement pure interfaces using small pieces of impure code, for use in circumstances where there is no feasible way to implement that same interface using pure code. Most Mercury programs do not use impure code at all. The ones that do make use of it use it very sparingly, with 99.9+% of their code being pure Mercury.