This is a summary of the subset of Prolog that we have learned so far in Non-Procedural Programming.
A single-line comment begins with %
and extends to the end of the line. Comments delimited with /*
and */
can extend over multiple lines.
All data in Prolog is represented as terms. A term is any of these:
an atom, which may have either of these syntactic forms:
a string beginning with a lowercase letter and containing
letters, digits and '_'. Examples: abc
,
joe
, orange_tree
.
a string consisting of punctuation characters. Examples: &&
,
$$$
, !@!
.
an number, which can be either an integer (e.g. 23 or -589) or a floating-point number (e.g. 5.27981). Integers may be of arbitrary size.
a variable, which begins with an uppercase letter and may contain letters, digits, and '_'.
a structure (compound term), which consists of a functor and zero or more components. The functor has the same syntax as an atom. The components are arbitrary terms. Examples:
point(
3
,
4
)
seg(point(X, Y), point(
4
,
2
))
date(
1
,
july
, X)
a list, which is a structure with a special syntax. A list contains zero or more comma-separated terms, enclosed in brackets:
[3, 4, 5] [A, 3, [B, C]] []
A Prolog list is a linked list, and has the corresponding performance characteristics: the head is directly accessible, and prepending a value is a constant-time operation.
A term specifying a list may optionally include a vertical bar (|). In this case, the element after the vertical bar is a list containing all remaining items. For example, all of the following are equivalent:
[3, 4, 5] [3 | [4, 5]] [3, 4 | [5]] [3, 4, 5 | []]
A predicate in Prolog has a name and zero or more arguments. A predicate is defined by a series of clauses, which must appear together in a source file.
A clause is either a fact or a rule.
A fact contains a predicate name plus zero or more arguments:
color(blue). is_power_of_two(1). parent(eliska, karel). contains(X, box(X)).
A rule consists of a head and a body,
separated by the symbol :-
(pronounced "if"):
path(X, Y) :- edge(X, Z), path(Z, Y). different(P, Q, R) :- dif(P, Q), dif(Q, R), dif(P, R).
The head looks like a fact. The body contains one or more goals, which look like facts. Goals can be chained together using the operators
,
("and")
;
("or")
A query in Prolog looks like the body of a rule: it
contains one or more goals, possibly chained together with ',
'
and/or ';
' .
is_prime(71). parent(X, eliska). color(C), color(D), dif(C, D), similar(C, D).
Arguments in predicates listed below include the following mode indicators. (These are not part of the Prolog language; they are merely a documentation convention.)
? : an argument that can be used for input or output: it may be unbound, partially instantiated, or fully instantiated
+ : an input argument: it must be fully instantiated
- : an output argument: it must be unbound
?Term1 =
?Term2
True if two terms can be unified.
dif
(?Term1, ?Term2)
True if two terms cannot be unified. This is a constraint that belongs to the pure language.
+Term1 @<
+Term2
+Term1
@>
+Term2
Tests whether Term1 precedes or follows Term2 in the standard order of terms:
numbers < atoms < lists, structures
Numbers are compared by value.
Atoms are compared alphabetically.
Lists are compared lexicographically: first by their first element, then their second element, and so on. (This is actually a special case of structure comparison.)
Structures are compared first by their arity (number of arguments), then by their functor name (alphabetically), then by their arguments, leftmost first.
atom
(+Term)
True if Term is bound to an atom.
atomic
(+Term)
True if Term is bound (i.e. not a variable) and is not compound.
compound
(+Term)
True if Term is bound to a compound term, i.e. a structure.
float
(+Term)
True if Term is bound to a floating-point number.
integer
(+Term)
True if Term is bound to an integer.
number
(+Term)
True if Term is bound to an integer or floating-point number.
fail
false
Always fail. The two forms are equivalent.
true
Always succeed.
!
Cut. Discard all choice points created since entering the predicate in which the cut appears.
\+
+Goal
True if Goal cannot be proven.
(P -> Q ; R)
If P then Q else R. This predicate behaves as if defined by
(P -> Q ; R) :- P, !, Q. (P -> Q ; R) :- R.
An arithmetic expression is a number, a variable, or a compound expression built using these operators:
+
: addition
-
: subtraction
*
: multiplication
/
: floating-point division
div
: integer division, rounding
toward negative infinity
mod
: modulus, i.e. remainder
after integer division
^
: exponentiation
abs
(Expr):
absolute value
max
(Expr1, Expr2)
: maximum of two values
min
(Expr1, Expr2):
minimum of two values
inf
: positive infinity
between
(+Low, +High,
?Value)
True if all arguments are integers and Low ≤ Value ≤ High. This predicate can generate all values between Low and High.
?Number
is
+Expr
True if Expr evaluates to Number.
+Expr1 =:=
+Expr2
+Expr1
=\=
+Expr2
+Expr1 >
+Expr2
+Expr1 >=
+Expr2
+Expr1 <
+Expr2
+Expr1 =<
+Expr2
Evaluate two arithmetic expressions
and compare the results. =:=
means
"equals". =\=
means "does
not equal".
To use these constraints, you must import the clpfd
module:
?- use_module(library(clpfd)).
I recommend putting the preceding command into the file ~/.swiplrc
so that it will automatically run at the beginning of each session.
?Expr1 #=
?Expr2
?Expr1
#\=
?Expr2
?Expr1 #>
?Expr2
?Expr1 #>=
?Expr2
?Expr1 #<
?Expr2
?Expr1 #=<
?Expr2
Compare
arithmetic expressions. #=
means
"equals". #\=
means
"does not equal". Unlike the predicates in the previous
section, these are true relations and will work in all directions.
?Var
in
+Domain
Var is an element of Domain. A domain can be any of these:
Integer : A single integer
Lower
..
Upper :
A range of integers. In a range, inf
and
sup
represent
negative and positive infinity.
Domain1
\/
Domain2 :
The union of two domains.
?Vars
ins
+Domain
All variables in the list Vars are elements of Domain.
all_distinct
(+Vars)
All of the given variables are distinct.
indomain
(+Var)
Assign a value to the given variable.
label
(+Vars)
Assign a value to each variable in Vars.
append
(?List1, ?List2,
?List1AndList2)
List1AndList2 is the concatenation of List1 and List2.
append
(+ListOfLists, ?List)
Concatenate a list of lists. (This is a single-level flatten operation.)
length(
?List, ?Int)
True if Int is the number of elements in List.
max_list(
?List, -Max)
True if Max is the largest number in List. Fails if List is empty.
member
(?Elem, ?List)
True if Elem is a member of List.
min_list(
?List, -Max)
True if Max is the smallest number in List. Fails if List is empty.
msort
(+List,
-Sorted)
Sort a list by the standard order of terms, keeping duplicate elements.
nextto
(?X,
?Y, ?List)
True if Y directly follows X in List.
nth1
(?Index,
?List,
?Elem)
True
if the Index'th
element of List
is
Elem.
The first element has index 1. For example, nth1(3,
L, E)
will
unify E with the third element in list L.
numlist
(+Low,
+High,
-List)
True if List is the list [Low, Low + 1, …, High]. Fails if High < Low.
permutation
(?Xs,
?Ys)
True if Xs is a permutation of Ys.
reverse
(?List1,
?List2)
True if List1 contains the same elements as List2 in reverse order.
same_length
(?List1,
?List2)
True if List1 and List2 have the same number of elements.
select
(?Elem,
?List1,
?List2)
True when List1, with Elem removed, results in List2.
select
(?X,
?XList,
?Y,
?YList)
True if XList and YList are identical except for a single element, which is X in XList and is Y in YList.
sort
(+List,
-Sorted)
Sort a list by the standard order of terms, removing duplicate elements.
sort
(+Key,
+Order,
+List,
-Sorted)
Sort a list. If Key is 0, each list element itself is the comparison key. If Key is a positive integer N, then each element must be a structure (i.e. compound term); the Nth element of the structure is used as the comparison key.
Order may be one of the following:
@<
:
sort in ascending order, removing duplicates
@=<
:
sort in ascending order, keeping duplicates
@>
:
sort in descending order, removing duplicates
@>=
:
sort in descending order, keeping duplicates
subset
(+SubSet,
+Set)
True if all elements of SubSet are present in Set.
call
(+Goal,
+ExtraArg1,
...)
Invoke Goal as a goal, appending extra arguments ExtraArg1, ExtraArg2, … to the argument list.
foldl
(+Goal, ?List,
?V0, ?V)
foldl
(+Goal,
?List, ?List1, ?V0, ?V)
Fold List from the left,
applying Goal to each element and an accumulator argument that
is initially V0. For example, foldl(G,
[a, b, c], V0, V)
will apply
G(a, V0, V1) G(b, V1, V2) G(c, V2, V)
The versions with extra arguments are similar, but operate on pairs or triples of elements from multiple lists.
maplist
(+Goal,
?List)
maplist
(+Goal,
?List1, ?List2)
maplist
(+Goal,
?List1, ?List2,
?List3)
True if Goal can successfully be applied to all elements of List. The versions with extra arguments are similar, but operate on pairs or triples of elements from multiple lists.
display
(+Term)
Write a term in expanded form,
displaying operators as ordinary functors. For example, display(2
+ 3 + 4)
writes "+(+(2,3),4)
".
nl
Write a newline to standard output.
write
(+Term)
Write Term to standard output.
writeln
(+Term)
Write Term to standard output, followed by a newline.
nodebug
Stop debugging.
trace(
+Pred)
(+Pred,
+Ports)
trace
Put a trace point on the given predicate. Ports is a single tracing port or a list of ports; the available ports are (call, redo, exit, fail). If you omit the port list, all ports are traced.
See more hints on debugging/tracing in the lecture notes.