The semantics of definite clauses should be fairly clear from the informal interpretations already given. However, it is useful to have a precise definition. The declarative semantics of definite clauses tells us which goals can be considered true according to a given program, and is defined recursively as follows:
A goal is true if it is the head of some clause instance and each of the goals (if any) in the body of that clause instance is true, where an instance of a clause (or term) is obtained by substituting, for each of zero or more of its variables, a new term for all occurrences of the variable.
For example, if a program contains the procedure for
declared in ref-sem-pro, then the declarative semantics tells us that
(A) is true, because this goal is the head of a certain instance of
the second clause (K) for
concatenate/3, namely (B), and we
know that the only goal in the body of this clause instance is true,
because it is an instance of the unit clause that is the first clause
concatenate([a], [b], [a,b])
concatenate([a], [b], [a,b]):- concatenate(, [b], [b]).
Note that the declarative semantics makes no reference to the sequencing of goals within the body of a clause, nor to the sequencing of clauses within a program. This sequencing information is, however, very relevant for the procedural semantics that Prolog gives to definite clauses. The procedural semantics defines exactly how the Prolog system will execute a goal, and the sequencing information is the means by which the Prolog programmer directs the system to execute his program in a sensible way. The effect of executing a goal is to enumerate, one by one, its true instances. Here is an informal definition of the procedural semantics.
To execute a goal, the system searches forwards from the beginning of the program for the first clause whose head matches or unifies with the goal. The unification process (see "A Machine-Oriented Logic Based on the Resolution Principle" by J.A. Robinson, Journal of the ACM 12:23-44, January 1965) finds the most general common instance of the two terms, which is unique if it exists. If a match is found, the matching clause instance is then activated by executing in turn, from left to right, each of the goals (if any) in its body. If at any time the system fails to find a match for a goal, it backtracks; that is, it rejects the most recently activated clause, undoing any substitutions made by the match with the head of the clause. Next it reconsiders the original goal that activated the rejected clause, and tries to find a subsequent clause that also matches the goal.
For example, if we execute the goal expressed by the query (A) we find
that it matches the head of the second clause for
X instantiated to
[a|X1]. The new variable
X1 is constrained by the
new goal produced, which is the recursive procedure call (B) and this
goal matches the second clause, instantiating
yielding the new goal (C).
| ?- concatenate(X, Y, [a,b]). (A)
concatenate(X1, Y, [b]) (B)
concatenate(X2, Y, ) (C)
Now this goal will only match the first clause, instantiating both
. Since there are no further goals to be executed, we have
X = [a,b] Y = 
That is, the following is a true instance of the original goal:
concatenate([a,b], , [a,b])
If this solution is rejected, backtracking will generate the further solutions
X = [a] Y = [b] X =  Y = [a,b]
in that order, by re-matching goals already solved once using the first
concatenate/3, against the second clause.