Hi,

In the Fall of 2001, I was a Graduate Teaching Assistant for a

class at my University. At one point the students had to program in

Prolog, which almost none of them had ever programmed in (Prolog was

not a prerequisite for this class). Most students only knew Lisp and

either C++ or Java.

When the instructor taught the students Prolog for the first time,

I noticed that many students failed to completely grasp the concepts

that were contained in Prolog. They could understand really simple

lines of Prolog, but when it came to learning how to write the code

for "append", many students were lost (mainly because the code looked

nothing like its C/C++/Java/Lisp counterparts).

A problem instructors have with teaching new students is that it's

not always obvious to the instructor what concepts are difficult to

the students (that's one reason that having a Graduate Teaching

Assistant around is a good idea).

Since I was a Teacher's Assistant, I was learning Prolog for the

second time and therefore able to discern exactly what it was that was

giving the students a difficult time learning Prolog: unlike Lisp,

C++, and Java, Prolog had a totally different programming paradigm

that the students had never been exposed to. This "paradigm shift" is

difficult for the professor to detect, since he or she has programmed

in Prolog for so long that it no longer is obvious what is difficult

for the new learner.

Therefore, I wrote this write-up for my class to help the students

"get the hang of" this new paradigm. I avoided technical wording

because my primary goal was to have my students understand how Prolog

"saw" the world, and how it did this differently than C++, Java, and

Lisp.

I'm posting the write-up here on the hope that somebody somewhere

might find it useful. Keep in mind that my goal in composing the

write-up was to use simple, understandable wording (instead of aiming

for technical completeness). Anybody who has basic knowldege of

Prolog and knowledge of either Lisp, C, C++, or Java should be able to

understand my write-up. (It is assumed that the reader of this

document already knows about the "|" operator. The "!" operator,

however, is never talked about here.)

I am by no means a Prolog guru or expert. Therefore there might be

a lot of places where an expert in Prolog might wish that the wording

was different, or that a concept I presented was not technically

correct. This was the best I could do on my limited knowledge of

Prolog, but nevertheless, many students found my document useful. My

write-up received a lot of positive feedback from the students, even

though it was about 11 pages long. (Several of the students who

bothered to read it all the way through told me that they were glad

they did, even though they thought they knew Prolog well enough before

reading my write-up.)

Feel free to distribute my write-up, especially for educational

purposes. I would ask, however, that my write-up not be changed

unless it is to correct an error.

Finally, here is my write-up:

---------------------------------------------------------

---------------------------------------------------------

UNDERSTANDING PROLOG (A LITTLE BETTER)

by Jean-Luc Romano

-----------------------------------------------

INTRODUCTION

You've tackled Java, taken on Lisp, and now you're learning Prolog.

You've certainly proven that you can learn new programming languages,

but Prolog doesn't strike you as being like any other programming

language that you've seen before.

If you find yourself struggling to understand even a very basic set

of rules in Prolog, then perhaps this file will help you understand

some fundamentals of Prolog.

-----------------------------------------------

UNDERSTANDING THE PROLOG PARADIGM:

LOOKING AT THE WORLD THE WAY PROLOG SEES IT

One of the areas that causes the most confusion in Prolog is that

many users new to Prolog want to treat the Prolog functors like

functions in C/C++, Java, or Lisp. Since Prolog functors look a lot

like the functions in these other languages, it's easy to understand

how this mistake might be made. Therefore, let's first look at this

first difference.

Let's define a function designed to find the square of a number.

It might look like this:

float square(float a) { return a*a; }; /* for C/C++ and Java */

(defun square (a) (* a a)) ; for Lisp

Let's examine what's going on: basically, in each of the

languages, we are passing in the value we want squared. The value is

squared, then returned. Simple, isn't it?

This is where Prolog is different. In Prolog, there are no return

values. Values are simply passed into a functor as a statement, and

then Prolog declares whether the statement can be proven true.

Therefore, BOTH the value to be squared AND the result should be

passed in; THEN we get to know if those values form a valid

combination.

To understand, review the following lines of code, noticing that

they now return boolean values (instead of the square of the number):

boolean square(float a, float b) { return (b == a*a;) } /*

C/C++/Java */

(defun square (a b) (= b (* a a))) ; Lisp

square(A,B) :- B is A * A. % Prolog

You probably understand what the first two lines of code are doing,

so let's review the Prolog line (the third line).

When you query Prolog with a statement like square(3,9) you are

asking Prolog if it can prove the statement as being true. Looking

back at the code we typed in, we see that Prolog will state any

statement that can bind to square(A,B) as being true if it can prove

that the statement "B is A * A" is true. Therefore, when you type

"square(3,9)." Prolog tries to prove that "9 is 3 * 3." Since this is

a rather trivial mathematical operation for Prolog to prove, it will

have no problem proving that statement as true. Because it determines

that 9 is in fact equal to 3 * 3, it then displays "yes", meaning that

it was able to prove square(3,9) as being true.

A few things to note:

- If Prolog ever displays "no" it does not

necessarily mean that the statement is false,

but rather that it was unable to be proven true.

You will find, however, that sometimes Prolog

will end up in an infinite loop (rather than

displaying "yes" or "no") when it is unable to

prove a true statement as true.

- If you've ever wondered why the keyword "is"

is used when comparing one mathematical value

to another, it is because the equal sign ("=")

is already reserved for the bind operation (for

example, List1 = [a,b,c] means that the variable

named "List1" binds to [a,b,c]).

- Remember, Prolog never returns a value, it

simply states whether or not it can prove the

statement (with its parameters) as being true.

Whereas in other languages you would write a

function to return a desired value, in Prolog

you would write code that, given all the

parameters, would say that all the parameters

and values fit together to make a true statement.

This is one of Prolog's main differences from

many other programming languages.

-----------------------------------------------

AN EXTRA FEATURE OF PROLOG

There's a handy feature of Prolog that hasn't been mentioned yet in

this file which you probably know about if you've studied even a

little bit of Prolog. Not only will Prolog try to prove a statement

(with all its parameters) as being true, but if you replace a

parameter value with a variable, it will try to find a value for the

variable that makes the statement true! To clarify, we all know that

Prolog will say the following is true:

square(6,36).

We typed this already knowing that the square of 6 is 36. But what

if we don't know that? What if we enter a huge number whose square we

don't know? If this is the case, we can put a variable name

(remember: variable names always start with a capital letter in

Prolog!) in place of where the squared value should be, like this:

square(17,SquaredValue).

Prolog then says:

SquaredValue = 289

This means that Prolog was able to able to prove

"square(17,SquaredValue)" as true, provided that SquaredValue binds to

289.

So, can you do it the other way around? In other words, can you

put a variable name in for the first parameter, and have it show you

the square root, like this?:

square(SquareRoot,9).

Well... sometimes, depending on how well you wrote your program. This

particular example gives me an error message, most likely because

Prolog wasn't made to "undo" a multiplication operation.

Theoretically it COULD go through the set of all real numbers, but

since it would have an infinite number of values to test, it's

possible that Prolog would never show you any value at all.

However, most code you will write in Prolog will deal with lists

instead of mathematical operations (after all, if we wanted to use

many mathematical operations, we would probably write our program in

C/C++ or Lisp, wouldn't we?...). And when dealing with lists it's

much easier to write code that works "the other way around," or that

fills in the missing piece (the parameter that is replaced with a

variable). But even here you need to be careful that you don't send

Prolog into a near-infinite loop.

-----------------------------------------------

TRY THIS AT HOME

Say you want to find the square of some number, for example, 15.

Now type the following into Prolog:

square(15).

You will probably see something similar to the following message:

++Error: Undefined predicate: square / 1

Aborting...

So what does this mean? Did we misspell the word "square"? Did we

type the code for "square" incorrectly? Did we find a number that the

functor does not work correctly with? Or did we just find a bug in

Prolog?

Actually, none of the above are correct. Do you know what's wrong?

We made the error of confusing Prolog usage with C/C++, Java, and

Lisp
...

**read more »**