Previous | Table of Contents | Next |
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.
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.
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.plthat 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, lets leave imperative programming aside and concentrate on declarative programming in Prolog.
The Hello World program is the standard introductory program for imperative languages. However, the standard introduction to Prologs 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 Is father was Henry VIII.
6.2.2.1. The Genealogy Program in Detail
Lets 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 dont 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 |