Previous Table of Contents Next


6.1.5. The Structure of This Chapter

This chapter continues with an introduction to Prolog programming in section 6.2; section 6.3 concerns more advanced features. Section 6.4 is titled “Tips and Traps” and deals with useful hints and difficult problems. Finally, section 6.5 contains several sample programs, section 6.6 gives acknowledgments, and section 6.7 lists references.

6.2. Basic Prolog Programming

This section covers the basics of Prolog programming. It first looks at the operation of the Prolog interpreter and then explores a simple knowledge-base program with simple terms. It then moves on to studying the properties of the equality predicate and lists terms made up of simpler terms. Finally, this section looks at the execution model that Prolog uses in order to do what it does.

6.2.1. Hello World

Prolog is a declarative language, but it has a procedural subset to deal with input/output. Here, I introduce simple interaction with the Prolog interpreter using this procedural subset and the popular Hello World program.

When we start the Prolog interpreter, it prompts us with something like

   |?-

This prompt is referred to as the query prompt, and the things we type to it are referred to as queries. To this query prompt, type the query

   |?- write(‘Hello world.’), nl.

(Bold font indicates what the interpreter types, and typewriter font indicates what we type.) This query asks Prolog to write the text Hello world. and then output a newline character (nl). Prolog should respond with

   Hello world.

   yes
   |?-

It has written the string we asked it to, started a new line, reported on the success of its task with yes, and is prompting us again. On some interpreters, we may have to press Enter once to get the top-level prompt back. The interpreter goes through an infinite loop of reading a query, responding to it, and waiting for another query.

Prolog programs are generally stored in files. Create a file called greet.pl, containing just the line

   hello :- write(‘Hello world.’), nl.

We can read this as saying the following to Prolog: To perform the task called hello, it should write the text Hello world. and output a newline. hello is called a predicate, and we have defined the predicate using a rule. A rule contains a head, in this case hello, and a body, everything after the :-. Back in the Prolog interpreter, we can now type the query

   |?- [greet].

This causes Prolog to “consult” the file greet.pl—that is, to read it as a Prolog source file. If we now pose the query

   |?- hello.

it responds exactly as if we had typed the rule body. We can also pose the query

   |?- hello, hello, hello.

This asks Prolog to perform the hello task three times, so Prolog prints the message three times:

   Hello world.
   Hello world.
   Hello world.

   yes
   |?-

Predicates can have parameters. Add the following definition to greet.pl:

This rule defines another predicate, hello_age, which takes one parameter, N. Now if we reconsult the source file using [greet] again and pose the query hello_age(72), it should write

   Hello 72-year-old.

We will explore I/O in more detail later, but for now, let’s leave imperative programming aside and concentrate on declarative programming in Prolog.

6.2.2. The Genealogy Program

The Hello World program is the standard introductory program for imperative languages. However, the standard introduction to Prolog’s declarative capabilities is the Genealogy program. Here we look at this simple knowledge-base program in detail.

Listing 6.1. A simple genealogy program in Prolog.

   % father(X, Y):  Y is the father of X
   father(henry_viii, henry_vii).
   father(margaret_tudor, henry_vii).
   father(mary_queen_of_scots, james_v_of_scotland).
   father(elizabeth_i, henry_viii).
   father(james_v_of_scotland, james_iv_of_scotland).

   % mother(X, Y):  Y is the mother of X
   mother(james_v_of_scotland, margaret_tudor).
   mother(james_vi_of_scotland, mary_queen_of_scots).

   hello_age(N) :-

    write(‘Hello ‘),
    write(N),
    write(‘-year-old.’),
    nl.

Consider the text in Listing 6.1, which constitutes a perfectly valid Prolog program. This particular program concerns relationships among some people in the English and Scottish royal families in the Middle Ages. The program defines two predicates, father and mother, by listing pairs of people (X, Y) such that Y is the father of X and pairs of people (X, Y) such that Y is the mother of X. For instance, the text father(elizabeth_i, henry_viii) is intended to state that Elizabeth I’s father was Henry VIII.

6.2.2.1. The Genealogy Program in Detail

Let’s consider the features of this program in detail. The first line, beginning with a percent sign, is a comment. Prolog ignores everything after a percent sign on any line. This comment describes the intended meaning of the father predicate; if father(X, Y) holds true for some X and Y, then it is supposed to be the case that Y is the father of X. The other line beginning with a percent sign is a comment describing the intended meaning of the mother predicate. It is useful to have such a comment for every predicate in a program.

We have chosen a Prolog constant, such as henry_viii, to represent each person of interest. Any sequence of alphanumeric characters and underscores beginning with a lowercase letter is a constant. In the last section, we encountered two other kinds of constants: any sequence of characters between single quotes, such as ‘Hello world’, and any integer, such as 72. Here, obviously, henry_viii is supposed to represent Henry VIII, and so on. We don’t have to declare constants; any use of a constant immediately makes the constant known to Prolog.

Each predicate is intended to be used to express some statement, as is usual in the realm of predicate logic. Predicate names have the same form as the alphanumeric or single-quoted constants (although the alphanumeric form is much more common to see).


Previous Table of Contents Next