Now that we’ve got some idea of what Prolog does, it’s time to go back to the beginning and work through the details more carefully. Let’s start by asking a very basic question: we’ve seen all kinds of expressions (for example jody , playsAirGuitar(mia) , and X ) in our Prolog programs, but these have just been examples. It’s time for precision: exactly what are facts, rules, and queries built out of?
The answer is terms, and there are four kinds of term in Prolog: atoms, numbers, variables, and complex terms (or structures). Atoms and numbers are lumped together under the heading constants, and constants and variables together make up the simple terms of Prolog.
Let’s take a closer look. To make things crystal clear, let’s first be precise about the basic characters (that is, symbols) at our disposal. The upper-case letters are A , B ,…, Z ; the lower-case letters are a , b ,…, z ; the digits are 0 , 1 , 2 ,…, 9 . In addition we have the _ symbol, which is called underscore, and some special characters , which include characters such as + , - , * , / , < , > , = , : , . , & , ~ . The blank space is also a character, but a rather unusual one, being invisible. A string is an unbroken sequence of characters.
An atom is either:
- A string of characters made up of upper-case letters, lower-case letters, digits, and the underscore character, that begins with a lower-case letter. Here are some examples: butch , big_kahuna_burger , listens2Music and playsAirGuitar .
- An arbitrary sequence of characters enclosed in single quotes. For example ’ Vincent ’, ’ The Gimp ’, ’ Five_Dollar_Shake ’, ’ &^%&#@$ &* ’, and ’ ’. The sequence of characters between the single quotes is called the atom name. Note that we are allowed to use spaces in such atoms; in fact, a common reason for using single quotes is so we can do precisely that.
- A string of special characters. Here are some examples: @= and ====> and ; and :- are all atoms. As we have seen, some of these atoms, such as ; and :- have a pre-defined meaning.
Real numbers aren’t particularly important in typical Prolog applications. So although most Prolog implementations do support floating point numbers or floats (that is, representations of real numbers such as 1657.3087 or π ) we say little about them in this book.
But integers (that is: …,-2, -1, 0, 1, 2, 3,…) are useful for such tasks as counting the elements of a list, and we’ll discuss how to manipulate them in Chapter 5 . Their Prolog syntax is the obvious one: 23 , 1001 , 0 , -365 , and so on.
A variable is a string of upper-case letters, lower-case letters, digits and underscore characters that starts either with an upper-case letter or with an underscore. For example, X , Y , Variable , _tag , X_526 , List , List24 , _head , Tail , _input and Output are all Prolog variables.
The variable _ (that is, a single underscore character) is rather special. It’s called the anonymous variable , and we discuss it in Chapter 4 .
Constants, numbers, and variables are the building blocks: now we need to know how to fit them together to make complex terms. Recall that complex terms are often called structures.
Complex terms are build out of a functor followed by a sequence of arguments. The arguments are put in ordinary parentheses, separated by commas, and placed after the functor. Note that the functor has to be directly followed by the parenthesis; you can’t have a space between the functor and the parenthesis enclosing the arguments. The functor must be an atom. That is, variables cannot be used as functors. On the other hand, arguments can be any kind of term.
Now, we’ve already seen lots of examples of complex terms when we looked at the knowledge bases KB1 to KB5. For example, playsAirGuitar(jody) is a complex term: its functor is playsAirGuitar and its argument is jody . Other examples are loves(vincent,mia) and, to give an example containing a variable, jealous(marsellus,W) .
But the definition allows for more complex terms than this. In fact, it allows us to keep nesting complex terms inside complex terms indefinitely (that is, it is allows recursive structure). For example
is a perfectly acceptable complex term. Its functor is hide , and it has two arguments: the variable X , and the complex term father(father(father(butch))) . This complex term has father as its functor, and another complex term, namely father(father(butch)) , as its sole argument. And the argument of this complex term, namely father(butch) , is also complex. But then the nesting bottoms out, for the argument here is the constant butch .
As we shall see, such nested (or recursively structured) terms enable us to represent many problems naturally. In fact the interplay between recursive term structure and variable unification is the source of much of Prolog’s power.
The number of arguments that a complex term has is called its arity. For example, woman(mia) is a complex term of arity 1, and loves(vincent,mia) is a complex term of arity 2.
Arity is important to Prolog. Prolog would be quite happy for us to define two predicates with the same functor but with a different number of arguments. For example, we are free to define a knowledge base that defines a two-place predicate love (this might contain such facts as love(vincent,mia) ), and also a three-place love predicate (which might contain such facts as love(vincent,marsellus,mia) ). However, if we did this, Prolog would treat the two-place love and the three-place love as different predicates. Later in the book (for example, when we introduce accumulators in Chapter 5) we shall see that it can be useful to define two predicates with the same functor but different arity.
When we need to talk about predicates and how we intend to use them (for example, in documentation) it is usual to use a suffix / followed by a number to indicate the predicate’s arity. To return to KB2, instead of saying that it defines predicates
we should really say that it defines predicates
And Prolog can’t get confused about a knowledge base containing the two different love predicates, for it regards the love/2 predicate and the love/3 predicate as distinct.