You should always document you Prolog programs in order that other people (or you, at some later date) can understand what they are meant to do. There aren't rigid guidelines for this but there is a reasonably well established set of conventions, which are as follows:
+
(if the argument is instantiated whenever the
predicate is called), -
(if the argument is uninstantiated when
the predicate is called) or ?
(if the argument can be either
instantiated or uninstantiated when called).
Consider, for example, the following documentation for memberchk/2
:
checks if
% memberchk(+Element, +Set) % means the same thing, but may only be used to test whether a known % Element occurs in a known Set. In return for this limited use, it % is more efficient when it is applicable. memberchk(Element, [Element|_]) :- !. memberchk(Element, [_|Rest]) :- memberchk(Element, Rest).
Note the use of %
symbols at the start of lines which are
comments. When loading a program, Prolog ignores everything from this
symbol up to the end of the same line. Larger comments can be
enclosed between \*
and *\
symbols.
In the memberchk/2
example, Element
and Set
are
both allocated mode +
because both need to be instantiated for
the predicate to work as intended. Compare this to the definition of
member/2
(below), where either of the two elements may be either
instantiated or uninstantiated, as required, and are therefore given
?
as their mode declarations.
% member(?Element, ?Set) % is true when Set is a list, and Element occurs in it. It may be used % to test for an element or to enumerate all the elements by backtracking. % Indeed, it may be used to generate the Set! member(Element, [Element|_]). member(Element, [_|Rest]) :- member(Element, Rest).
One final point about these examples. Notice that an underscore to
represent an anonymous variable is used wherever the name
of a variable is unimportant. How do you know that it is unimportant?
If you see a clause in which a named variable appears only once then
its name doesn't matter since it isn't matching to anything in the
clause. For instance the first clause of member/2
could have
been:
member(Element, [Element|Rest]).but it isn't important to distinguish
Rest
with a special name,
so the convention is to use an underscore. Many Prolog systems will
generate warning messages when they find ``singleton'' variables, such
as Rest
in the example above. It is a good idea to get into
the habit of using underscores to avoid these warning messages. That
way, if you accidentally introduce a singleton variable ( e.g. by
mistyping the name of a variable) you will always be able to spot it
when you load the file and see the singleton warning message.