The best way to learn about goal-oriented programming is to read and write
goal-oriented programs in Prolog, for goal-oriented programming is what
Prolog is all about.
In broader terms, the evolution of computer languages is an evolution away
from low-level languages, in which the programmer specifies how something is to be done [otherwise known as imperative languages - NBN],
toward high-level languages, in which the programmer specifies simply
what is to be done [declarative languages; Prolog and SQL are
examples of such languages - NBN]. With the development of Fortran, for
example, programmers were no longer forced to speak to the computer in the
procrustian low-level language of addresses and registers. Instead, Fortran
programmers could speak in their own language, or nearly so, using a
notation that made only moderate concessions to the one-dimensional,
80-column world.
The chapters of this book [Bratko] clearly illustrate the difference between
how-type and what-type thinking. In the first chapter, for example, the
difference is illustrated through problems dealing with family relations.
The Prolog programmer straightforwardly describes the grandfather concept in
explicit, natural terms: a grandfather is a father of a parent. Here is the
Prolog notation:
grandfather(X, Z) :- father( X, Y), parent( Y, Z).
Once Prolog knows what a grandfather is, it is easy to ask a question: who
are Patrick's grandfathers, for example. Here again is the Prolog notation,
along with a typical answer:
?- grandfather( X, patrick).
X = james;
X = carl
It is Prolog's job to figure out how to solve the problem by combing through
a database of known father and parent relations. The programmer specifies
only what is known and what question is to be solved. The programmer is more
concerned with knowledge and less concerned with algorithms that exploit the
knowledge.
As the hierarchy of families is well-known to everybody, almost all
Prolog books begin with the same type of database. For example, the
database that I have been using to test my interpreter is as follows
parent (noam, netta).
parent (noam, nir).
parent (sarit, netta).
parent (sarit, nir).
male (noam).
male (nir).
female (sarit).
female (netta).
female (shaked).
female (lior).
female (romi).
parent (netta, shaked).
parent (netta, lior).
parent (nir, romi).
father (X, Y):- male(X), parent(X, Y).
mother (X, Y):- female(X), parent(X, Y).
grandparent (X, Y):- parent(X, Z), parent(Z, Y).
As a result, I can ask who is a mother (and who are her children), who is
a father, and who is a grandparent, receiving answers (solutions)
even though these answers are not contained within the database.
This is what I call the deceptive simplicity of Prolog. If this doesn't
interest you, then don't read on.
I was thinking last night in bed (an activity that normally would prevent
me from falling asleep) how to represent the 'sister' relationship. Note
that technically there are two different relationships here: Netta is
Nir's sister (singular), but Netta and Nir are not sisters (plural). On
the other hand, Shaked is Lior's sister, and Shaked and Lior are sisters.
At the moment, I am going to model the simpler 'sister' relationship. as
follows
sister (X, Y):- female (X), parent (Z, X), parent (Z, Y).
In English, this says that one person is the sister of another if the first person is female and the two people share a parent.
Running the query ?- sister (X, Y). in the interpreter reveals a few problems, one of which I knew about in advance, and one unexpected problem which is a bug. The unexpected bug is that the interpreter also shows the value of the intermediate Z variable; this should not happen. This is easily fixed: CP solved the problem with what I would call a hack, by storing any variables in the original query in a list, then when printing solutions, this list is checked to see which variables should be displayed.
I'll discuss the sister query in a separate post.
No comments:
Post a Comment