Navigation  without Java Scripts

Chapter 2. Visual Prolog Programs

The syntax of Visual Prolog is designed to express knowledge about properties and relationships. You've already seen the basics of how this is done; in Chapter 2 you learned about clauses (facts and rules), predicates, variables, and goals.

Unlike other versions of Prolog, Visual Prolog is a typed Prolog compiler; you declare the types of the objects that each predicate applies to. The type declarations allow Visual Prolog programs to be compiled right down to native machine code, giving execution speeds similar to those of compiled C and pascal.

We discuss the four basic sections of a Visual Prolog program--where you declare and define the predicates and arguments, define rules, and specify the program's goal--in the first part of this chapter. In the second part of this chapter we take a closer look at declarations and rule syntax. Then, at the end of this chapter, we briefly introduce the other sections of a Visual Prolog program, including the facts, constants, and various global sections, and compiler directives.

Visual Prolog's Basic Program Sections

Generally, a Visual Prolog program includes four basic program sections. These are the clauses section, the predicates section, the domains section, and the goal section.

The clauses section is the heart of a Visual Prolog program; this is where you put the facts and rules that Visual Prolog will operate on when trying to satisfy the program's goal.

The predicates section is where you declare your predicates and the domains (types) of the arguments to your predicates. (You don't need to declare Visual Prolog's built-in predicates.)

The domains section is where you declare any domains you're using that aren't Visual Prolog's standard domains. (You don't need to declare standard domains.)

The goal section is where you put the starting goal for a Visual Prolog program.

The Clauses Section

The clauses section is where you put all the facts and rules that make up your program. Most of the discussion in Chapter 2 was centered around the clauses (facts and rules) in your programs; what they convey, how to write them, and so on.

If you understand what facts and rules are and how to write them in Prolog, you know what goes in the clauses section. Clauses for a given predicate must be placed together in the clauses section; a sequence of clauses defining a predicate is called a procedure.

When attempting to satisfy a goal, Visual Prolog will start at the top of the clauses section, looking at each fact and rule as it searches for a match. As Visual Prolog proceeds down through the clauses section, it places internal pointers next to each clause that matches the current subgoal. If that clause is not part of a logical path that leads to a solution, Visual Prolog returns to the set pointer and looks for another match (this is backtracking, which we mentioned in Chapter 2).

The Predicates Section

If you define your own predicate in the clauses section of a Visual Prolog program, you must declare it in a predicates section, or Visual Prolog won't know what you're talking about. When you declare a predicate, you tell Visual Prolog which domains the arguments of that predicate belong to.

Visual Prolog comes with a wealth of built-in predicates. You don't need to declare any of Visual Prolog's built-in predicates that you use in your program. The Visual Prolog on-line help gives a full explanation of the built-in predicates.

Facts and rules define predicates. The predicates section of the program simply lists each predicate, showing the types (domains) of its arguments. Although the clauses section is the heart of your program, Visual Prolog gets much of its efficiency from the fact that you also declare the types of objects (arguments) that your facts and rules refer to.

How to Declare User-Defined Predicates

A predicate declaration begins with the predicate name, followed by an open (left) parenthesis. After the predicate name and the open parenthesis come zero or more arguments to the predicate.

predicateName(argument_type1, argument_type2, ..., argument_typeN)

Each argument type is followed by a comma, and the last argument type is followed by the closing (right) parenthesis. Note that, unlike the clauses in the clauses section of your program, a predicate declaration is not followed by a period. The argument types are either standard domains or domains that you've declared in the domains section.

Predicate Names

The name of a predicate must begin with a letter, followed by a sequence of letters, digits, and underscores. The case of the letters does not matter, but we strongly recommend using only a lower-case letter as the first letter in the predicate name. (Other versions of Prolog don't allow predicate names to begin with upper-case letters or underscores, and future versions of Visual Prolog might not, either.) Predicate names can be up to 250 characters long.

You can't use spaces, the minus sign, asterisks, slashes, or other non-alphanumeric characters in predicate names. Valid naming charactersnaming characters in Visual Prolog consist of the following:

Upper-case Letters
: A, B, ... , Z
Lower-case Letters
: a, b, ... , z
Digits
: 0, 1, ... , 9
Underscore character
: _

All predicate names and arguments can consist of combinations of these characters, as long as you obey the rules for forming both predicate and argument names.

Below are a few examples of legal and illegal predicate names.

Legal Predicate Names Illegal Predicate Names
fact [fact]
is_a *is_a*
has_a has/a
patternCheckList pattern-Check-List
choose_Menu_Item choose Menu Item
predicateName predicate<Name>
first_in_10 >first_in_10

Predicate Arguments

The arguments to the predicates must belong to known Visual Prolog domains. A domain can be a standard domain, or it can be one you declare in the domains section.

Examples

If you declare a predicate my_predicate(symbol, integer) in the predicates section, like this:

PREDICATES
my_predicate(symbol, integer)

you don't need to declare its arguments' domains in a domains section, because symbol and integer are standard domains. But if you declare a predicate my_predicate(name, number) in the predicates section, like this:

PREDICATES
my_predicate(name, number)

you will need to declare suitable domains for name and number. Assuming you want these to be symbol and integer respectively, the domain declaration looks like this:

DOMAINS
name = symbol
number = integer
PREDICATES
my_predicate(name, number)

This program excerpt shows some more predicate and domain declarations:

DOMAINS
person, activity = symbol
car, make, color = symbol
mileage, years_on_road, cost = integer
PREDICATES
likes(person, activity)
parent(person, person)
can_buy(person, car)
car(make, mileage, years_on_road, color, cost)
green(symbol)
ranking(symbol, integer)

This excerpt specifies the following information about these predicates and their arguments:

The predicate likes takes two arguments (person and activity), both of which belong to unique symbol domains (which means that their values are names rather than numbers).

The predicate parent takes two person arguments, where person is a symbol type.

The predicate can_buy takes two arguments, person and car, which are also both symbol types.

The predicate car takes five arguments: make and color are of unique symbol domains, while mileage, years_on_road, and cost are of unique integer domains.

The predicate green takes one argument, a symbol: there is no need to declare the argument's type, because it's of the standard domain symbol.

The predicate ranking takes two arguments, both of which belong to standard domains (symbol and integer), so there is no need to declare the argument types.

Chapter 5, "Simple and Compound Objects," gives more detail about domain declarations.

The Domains Section

In traditional Prolog there is only one type; the term. We have the same in Visual Prolog, but we are declaring what the domains of the arguments to the predicates actually are.

Domains enable you to give distinctive names to different kinds of data that would otherwise look alike. In a Visual Prolog program, objects in a relation (the arguments to a predicate) belong to domains; these can be pre-defined domains, or special domains that you specify.

The domains section serves two very useful purposes. First, you can give meaningful names to domains even if, internally, they are the same as domains that already exist. Second, special domain declarations are used to declare data structures that are not defined by the standard domains.

It is sometimes useful to declare a domain when you want to clarify portions of the predicates section. Declaring your own domains helps document the predicates that you define by giving a useful name to the argument type.

Examples

Here's an example to illustrate how declaring domains helps to document your predicates:

Frank is a male who is 45 years old.

With the pre-defined domains, you come up with the following predicate declaration:

person(symbol, symbol, integer)

This declaration will work fine for most purposes. But suppose you want to maintain your code months after you've finished writing it. The preceding predicate declaration won't mean much to you in six months. Instead, the following declarations will help you understand what the arguments in the predicate declaration stand for:

DOMAINS
name, sex = symbol
age = integer
PREDICATES
person(name, sex, age)

One of the main advantages of this declarations, is that Visual Prolog can catch type errors, like the following obvious mistake

same_sex(X, Y) :-
person(X, Sex, _),
person(Sex, Y, _).

Even though name and sex are both defined as symbol, they are not equivalent to each other. This enables Visual Prolog to detect an error if you accidentally swap them. This feature is very useful when your programs get large and complex.

You might be wondering why we don't use special domains for all argument declarations, since special domains communicate the meaning of the argument so much better. The answer is that once an argument is typed to a specific domain, that domain can't be mixed with another domain you have declared, even if the domains are the same! So, even though name and sex are of the same domain (symbol), they can't be mixed. However, all user-defined domains can be matched with the pre-defined domains.

This next example program will yield a type error when run:

DOMAINS
product,sum = integer
 
PREDICATES
add_em_up(sum,sum,sum)
multiply_em(product,product,product)
 
CLAUSES
add_em_up(X,Y,Sum):-
Sum=X+Y.
 
multiply_em(X,Y,Product):-
Product=X*Y.

This program does two things: It adds and it multiplies. Given the goal

add_em_up(32, 54, Sum).

Visual Prolog will come up with

Sum=86
1 Solution

which is the sum of the two integers you supplied the program.

On the other hand, this program will also multiply two arguments with the multiply_em predicate. Now experiment with this program. If you need to figure out what the product of 31 and 13 is, you could enter the goal:

multiply_em(31, 13, Product).

Visual Prolog would then respond with the correct answer.

Product=403
1 Solution

But suppose you need the sum of 42 and 17; the goal for this would be

add_em_up(42, 17, Sum).

Now you need to double the product of 31 and 17, so you write the following goal:

multiply_em(31, 17, Sum), add_em_up(Sum, Sum, Answer).

You might expect Visual Prolog to return

Sum=527, Answer=1054
1 Solution

But, instead, you get a type error. What happened is that you tried to pass the resulting value of multiply_em (that is, of domain product), into the first and second arguments in add_em_up, which have domains of sum. This yields a type error because product is a different domain than sum. Even though both domains are really of type integer, they are different domains, and are treated as such.

So, if a variable is used in more than one predicate within a clause, it must be declared the same in each predicate. Be sure that you fully understand the concept behind the type error given here; knowing the concept will avoid frustrating compiler error messages. Later in this chapter we will describe the different automatic and explicit type-conversions Visual Prolog offers.

To further understand how you can use domain declarations to catch type errors, consider the following program example:

/* Program ch03e02.pro */

DOMAINS
brand,color = symbol
age = byte
price, mileage = ulong
 
PREDICATES
nondeterm car(brand,mileage,age,color,price)
 
CLAUSES
car(chrysler,130000,3,red,12000).
car(ford,90000,4,gray,25000).
car(datsun,8000,1,black,30000).

Here, the car predicate declared in the predicates section takes five arguments. One belongs to the age domain, which is of byte type. On the 'x86 family of CPUs, a byte is an 8-bit unsigned integer, which can take on values between 0 and 255, both inclusive. Similarly, the domains mileage and price are of type ulong, which is a 32-bit unsigned integer, and the domains brand and color are of type symbol.

We'll discuss the built-in domains in greater detail in a moment. For now, load and run this program and try each of the following goals in turn.

car(renault, 13, 40000, red, 12000).
car(ford, 90000, gray, 4, 25000).
car(1, red, 30000, 80000, datsun).

Each goal produces a domain error. In the first case, for example, it's because age must be a byte. Hence, Visual Prolog can easily detect if someone typing in this goal has reversed the mileage and age objects in predicate car. In the second case, age and color have been swapped, and in the third case you get to find out for yourself where the mixups are.

The Goal Section

Essentially, the goal section is the same as the body of a rule: it's simply a list of subgoals. There are two differences between the goal section and a rule:

The goal keyword is not followed by :-.

Visual Prolog automatically executes the goal when the program runs.

It's as if Visual Prolog makes a call to goal, and the program runs, trying to satisfy the body of the goal rule. If the subgoals in the goal section all succeed, then the program terminates successfully. If, while the program is running, a subgoal in the goal section fails, then the program is said to have failed. (Although, from an external point of view, there isn't necessarily any difference; the program simply terminates.)

 

A Closer Look at Declarations and Rules

Visual Prolog has several built-in standard domains. You can use standard domains when declaring the types of a predicate's arguments. Standard domains are already known to Visual Prolog and should not be defined in the domains section.

We'll first look at all the integral ones, shown in Table 3.1.

Table 3.1:Integral Standard Domains

Domain Description and implementation
short A small, signed, quantity.
All platforms 16 bits,2s comp 32768 .. 32767
ushort A small, unsigned, quantity.
All platforms 16 bits 0 .. 65535
long A large signed quantity
All platforms 32 bits,2s comp -2147483648 .. 2147483647
ulong A large, unsigned quantity
All platforms 32 bits 0 .. 4294967295
integer A signed quantity, having the natural size for the machine/platform architecture in question.
16bit platforms 16 bits,2s comp -32768 .. 32767
32bit platforms 32 bits,2s comp -2147483648 .. 2147483647
unsigned An unsigned quantity, having the natural size for the machine/platform architecture in question.
16bit platforms 16 bits 0 .. 65535
32bit platforms 32 bits 0 .. 4294967295
byte  
All platforms ³ 8 bits 0 .. 255
word  
All platforms 16 bits 0 .. 65535
dword  
All platforms 32 bits 0 .. 4294967295

 

Syntactically, a value belonging in one of the integral domains is written as a sequence of digits, optionally preceded by a minus-sign for the signed domains, with no white-space. There are also octal and hexadecimal syntaces for the integral domains; these will be illustrated in the language, chapter 9.

The byte, word, and dword domains are most useful when dealing with machine-related quantities, except perhaps for the byte; an 8-bit integral quantity can prove quite relevant, as we have already seen. For general use, the integer and unsigned quantities are the ones to use, augmented by the short and long (and their unsigned counterparts) for slightly more specialized applications. Generally, the most efficient code results from using what's natural for the machine; a short is not as efficient on a '386 platform as a long, and a long is not as efficient on a '286 platform as a short, hence the different implementations of integer and unsigned.

In domain declarations, the signed, and unsigned keywords may be used in conjunction with the byte, word, and dword built-in domains to construct new integral domains, as in

DOMAINS
i8 = signed byte

creating a new integral domain having a range of -128 to +127.

The other basic domains are shown in table 3.2. Visual Prolog recognizes several other standard domains, but we cover them in other chapters, after you've got a good grasp of the basics.

Table 3.2: Basic Standard Domains

Domain Description and implementation
Char A character, implemented as an unsigned byte. Syntactically, it is written as a character surrounded by single quotation marks: 'a'.
Real A floating-point number, implemented as 8 bytes in accordance with IEEE conventions; equivalent to C's double. Syntactically, a real is written with an optional sign (+ or -) followed by some digits DDDDDDD, then an optional decimal point (.) followed by more digits DDDDDDD, and an optional exponential part (e(+ or -)DDD):
<+|-> DDDDD <.> DDDDDDD <e <+|-> DDD>

Examples of real numbers:

42705 9999 86.72

9111.929437521e238 79.83e+21

Here 79.83e+21 means 79.83 x 10^21, just as in other languages.

The permitted number range is 1  ) 10-307 to 1  ) 10308 (1e-307 to 1e+308). Values from the integral domains are automatically converted to real numbers when necessary.

String A sequnce of characters, implemented as a pointer to a zero-terminated byte array, as in C. Two formats are permitted for strings:
1. a sequence of letters, numbers and underscores, provided the first character is lower-case; or

2. a character sequence surrounded by a pair of double quotation marks.

Examples of strings:

telephone_number "railway ticket" "Dorid Inc"

Strings that you write in the program can be up to 255 characters long. Strings that the Visual Prolog system reads from a file or builds up internally can be up to 64K characters long on 16-bit platforms, and (theoretically) up to 4G long on 32-bit platforms.

Symbol A sequence of characters, implemented as a pointer to an entry in a hashed symbol-table, containing strings. The syntax is the same as for strings.

Symbols and strings are largely interchangeable as far as your program is concerned, but Visual Prolog stores them differently. Symbols are kept in a look-up table, and their addresses, rather than the symbols themselves, are stored to represent your objects. This means that symbols can be matched very quickly, and if a symbol occurs repeatedly in a program, it can be stored very compactly. Strings are not kept in a look-up table; Visual Prolog examines them character-by-character whenever they are to be matched. You must determine which domain will give better performance in a particular program.

The following table gives some examples of simple objects that belong to the basic standard domains.

Table 3.3: Simple Objects

"&&", caitlin, "animal lover", b_l_t
(symbol or string)
-1, 3, 5, 0
(integer)
3.45, 0.01, -30.5, 123.4e+5
(real)
'a', 'b', 'c' '/', '&'
(char)

Typing Arguments in Predicate Declarations

Declaring the domain of an argument in the predicates section is called typing the argument. For example, suppose you have the following relationship and objects:

Frank is a male who is 45 years old.

The Prolog fact that corresponds to this natural language relation might be

person(frank, male, 45).

In order to declare person as a predicate with these three arguments, you could place the following declaration in the predicates section:

person(symbol, symbol, unsigned)

Here, you have used standard domains for all three arguments. Now, whenever you use the predicate person, you must supply three arguments to the predicate; the first two must be of type symbol, while the third argument must be an integer.

If your program only uses standard domains, it does not need a domains section; you have seen several programs of this type already.

Or, suppose you want to define a predicate that will tell you the position of a letter in the alphabet. That is,

alphabet_position(Letter, Position)

will have Position = 1 if Letter = a, Position = 2 if Letter = b, and so on. The clauses for this predicate would look like this:

alphabet_position(A_character, N).

If standard domains are the only domains in the predicate declarations, the program does not need a domains section. Suppose you want to define a predicate so that the goal will be true if A_character is the Nth letter in the alphabet. The clauses for this predicate would look like this:

alphabet_position('a', 1).
alphabet_position('b', 2).
alphabet_position('c', 3).
...
alphabet_position('z', 26).

You can declare the predicate as follows:

PREDICATES
alphabet_position(char, unsigned)

and there is no need for a domains section. If you put the whole program together, you get

PREDICATES
alphabet_position(char, integer)
 
CLAUSES
alphabet_position('a', 1).
alphabet_position('b', 2).
alphabet_position('c', 3).
/* ... other letters go here ... */
alphabet_position('z', 26).

Here are a few sample goals you could enter:

alphabet_position('a', 1).
alphabet_position(X, 3).
alphabet_position('z', What).

Exercises

Program 4 is a complete Visual Prolog program that functions as a mini telephone directorytelephone directory. The domains section is not needed here, since only standard domains are used.

/* Program ch03e04.pro */

PREDICATES
nondeterm phone_number(symbol,symbol)
 
CLAUSES
phone_number("Albert","EZY-3665").
phone_number("Betty","555-5233").
phone_number("Carol","909-1010").
phone_number("Dorothy","438-8400").

Load and run the program 4, then try each of these goals in turn:

a. phone_number("Carol", Number).

b. phone_number(Who, "438-8400").

c. phone_number("Albert", Number).

d. phone_number(Who, Number).

Now update the clauses. Suppose that Kim shares a condo with Dorothy and so has the same phone number. Add this fact to the clauses section and try the goal

phone_number(Who, "438-8400").

You should get two solutions to this query:

Who=Dorothy
Who=Kim
2 Solutions

To illustrate the char domain, program 5 defines isletter, which, when given the goals

isletter('%').
isletter('Q').

will return No and Yes, respectively.

/* Program ch03e05.pro */

PREDICATES
nondeterm isletter(char)
 
CLAUSES
/* When applied to characters, '<=' means */
/* "alphabetically precedes or is the same as" */
 
isletter(Ch):-
'a' <= Ch,
Ch <= 'z'.
 
isletter(Ch):-
'A' <= Ch,
Ch <= 'Z'.

Load and run Program 5 and try each of these goals in turn:

a. isletter('x').
b. isletter('2').
c. isletter("hello").
d. isletter(a).
e. isletter(X).

Goals (c) and (d) will result in a type error message, and (e) will return an Free variable message, because you can't test whether an unidentified object follows a or precedes z.

Multiple Arity

The arity of a predicate is the number of arguments that it takes. You can have two predicates with the same name but different arity. You must group different arity versions of a given predicate name together in both the predicates and clauses sections of your program; apart from this restriction, the different arities are treated as completely different predicates.

/* Program ch03e06.pro */

DOMAINS
person = symbol
 
PREDICATES
father(person) % This person is a father
father(person, person) % One person is the father of the other person
 
CLAUSES
father(Man):-
father(Man,_).
father(adam,seth).
father(abraham,isaac).

Rule Syntax

Rules are used in Prolog when a fact depends upon the success (truth) of another fact or group of facts. As we explained in Chapter 2, a Prolog rule has two parts: the head and the body. This is the generic syntax for a Visual Prolog rule:

HEAD :- <Subgoal>, <Subgoal>, ..., <Subgoal>.

The body of the rule consists of one or more subgoals. Subgoals are separated by commas, specifying conjunction, and the last subgoal in a rule is terminated by a period.

Each subgoal is a call to another Prolog predicate, which may succeed or fail. In effect, calling another predicate amounts to evaluating its subgoals, and, depending on their success or failure, the call will succeed or fail. If the current subgoal can be satisfied (proven true), the call returns, and processing continues on to the next subgoal. Once the final subgoal in a rule succeeds, the call returns successfully; if any of the subgoals fail, the rule immediately fails.

To use a rule successfully, Prolog must satisfy all of the subgoals in it, creating a consistent set of variable bindings as it does so. If one subgoal fails, Prolog will back up and look for alternatives to earlier subgoals, then proceed forward again with different variable values. This is called backtracking. A full discussion of backtracking and how Prolog finds solutions is covered in Chapter 4.

Prolog if Symbol vs. IF in Other Languages

As we have mentioned earlier, the :- separating the head and the body of a rule, is read "if". However, a Prolog if differs from the IF written in other languages, such as Pascal.

In Pascal, for instance, the condition contained in the IF statement must be met before the body of the statement can be executed; in other words,

"if HEAD is true, then BODY is true (or: then do BODY)"

This type of statement is known as an if/then conditional. Prolog, on the other hand, uses a different form of logic in its rules. The head of a Prolog rule is concluded to be true if (after) the body of the rule succeeds; in other words,

"HEAD is true if BODY is true (or: if BODY can be done)"

Seen in this manner, a Prolog rule is in the form of a then/if conditional.

Automatic Type Conversions

When Visual Prolog matches two variables, it's not always necessary that they belong to the same domain. Also, variables can sometimes be bound to constants from other domains. This (selective) mixing is allowed because Visual Prolog performs automatic type conversion (from one domain to another) in the following circumstances:

Between strings and symbols.

Between all the integral domains, and also real. When a character is converted to a numeric value, the number is the ASCII value for that character.

An argument from a domain my_dom declared in this form

DOMAINS
my_dom = <base domain> /*<base domain> is a standard domain */

can mix freely with arguments from that base domain and all other standard domains that are compatible with that base domain. (If the base domain is string, arguments from the symbol domain are compatible; if the base domain is integer, arguments from the real, char, word, etc., domains are compatible.

These type conversions mean, for example, that you can

call a predicate that handles strings with a symbol argument, and vice versa

call a predicate that handles reals with an integer argument

call a predicate that handles characters with integer values

use characters in expressions and comparisons without needing to look up their ASCII values.

There are a number of rules deciding what domain the result of the expression belongs to, when different domains are mixed. These will be detailed in chapter 9.

Other Program Sections

Now that you're reasonably familiar with the clauses, predicates, domains, and goal sections of a Visual Prolog program, we'll tell you a little bit about some other commonly-used program sections: the facts section, the constants section, and the various global sections. This is just an introduction; as you work through the rest of the tutorials in this book you'll learn more about these sections and how to use them in your programs.

The Facts Section

A Visual Prolog program is a collection of facts and rules. Sometimes, while the program is running, you might want to update (change, remove, or add) some of the facts the program operates on. In such a case, the facts constitute a dynamic or internal database; it can change while the program is running. Visual Prolog includes a special section for declaring the facts in the program that are to be a part of the dynamic (or changing) database; this is the facts section.

The keyword facts declares the facts section. It is here that you declare the facts to be included in the dynamic facts section. Visual Prolog includes a number of built-in predicates that allow easy use of the dynamic facts section. The keyword facts is synonymous with database.

Chapter 8 provides a complete discussion of the facts section and the predicates used along with it.

The Constants Section

You can declare and use symbolic constants in your Visual Prolog programs. A constant declaration section is indicated by the keyword constants, followed by the declarations themselves, using the following syntax:

<Id> = <Macro definition>

<Id> is the name of your symbolic constant, and <Macro definition> is what you're assigning to that constant. Each <Macro definition> is terminated by a newline character, so there can only be one constant declaration per line. Constants declared in this way can then be referred to later in the program.

Consider the following program fragment:

CONSTANTS
zero = 0
one = 1
two = 2
hundred = (10*(10-1)+10)
pi = 3.141592653
ega = 3
slash_fill = 4
red = 4

Before compiling your program, Visual Prolog will replace each constant with the actual string to which it corresponds. For instance:

...,
A = hundred*34, delay(A),
setfillstyle(slash_fill, red),
Circumf = pi*Diam,
...

will be handled by the compiler in exactly the same way as

...,
A = (10*(10-1)+10)*34, delay(A),
setfillstyle(4, 4),
Circumf = 3.141592653*Diam,
...

There are a few restrictions on the use of symbolic constants:

The definition of a constant can't refer to itself. For example:

my_number = 2*my_number/2 /* Is not allowed */

will generate the error message Recursion in constant definition.

The system does not distinguish between upper-case and lower-case in a constants declaration. Consequently, when a constants identifier is used in the clauses section of a program, the first letter must be lower-case to avoid confusing constants with variables. So, for example, the following is a valid construction:

CONSTANTS
Two = 2
GOAL
A=two, write(A).

There can be several constants declaration sections in a program, but constants must be declared before they are used.

Declared constants are effective from their point of declaration to the end of the source file, and in any files included after the declaration. Constant identifiers can only be declared once. Multiple declarations of the same identifier will result in the error message This constant is already defined.

The Global Sections

Visual Prolog allows you to declare some domains, predicates, and clauses in your program to be global (rather than local); you do this by setting aside separate global domains, global predicates, and global facts sections at the top of your program. These global sections are discussed in the chapter 17.

The Compiler Directives

Visual Prolog provides several compiler directives you can add to your program to tell the compiler to treat your code in specified ways when compiling. You can also set most of the compiler directives from the Options | Project | Compiler Options menu item in the Visual Prolog system. Compiler directives are covered in detail in the chapter 17, but you'll want to know how to use a couple of them before you get to that chapter, so we introduce the basic ones here.

The include Directive

As you get more familiar with using Visual Prolog, you'll probably find that you use certain procedures over and over again in your programs. You can use the include directive to save yourself from having to type those procedures in again and again.

Here's an example of how you could use it:

You create a file (such as MYSTUFF.PRO) in which you declare your frequently-used predicates (using domains and predicates sections) and give the procedures defining those predicates in a clauses section.

You write the source text for the program that will make use of these procedures.

At a natural boundary in your source text, you place the line

include "mystuff.pro"

(A natural boundary is anywhere in your program that you can place a domains, facts, predicates, clauses, or goal section.)

When you compile your source text, Visual Prolog will compile the contents of MYSTUFF.PRO right into the final compiled product of your source text.

You can use the include directive to include practically any often-used text into your source text, and one included file can in turn include another (but a given file can only be included once in your program). The include directive can appear at any natural boundary in your source text. However, you must observe the restrictions on program structure when you include a file into your source text.

Summary

These are the ideas we've introduced in this chapter:

A Visual Prolog program has the following basic structure:

DOMAINS
/* ...

domain declarations

... */
PREDICATES
/* ...

predicate declarations

... */
CLAUSES
/* ...

clauses (rules and facts)

... */
GOAL
/* ...
subgoal_1,
subgoal_2,
etc. */

The clauses section is where you put the facts and rules that Visual Prolog will operate on when trying to satisfy the program's goal.

The predicates section is where you declare your predicates and the domains (types) of the arguments to your predicates. Predicate names must begin with a letter (preferably lower-case), followed by a sequence of letters, digits, and underscores, up to 250 characters long. You can't use spaces, the minus sign, asterisks, or slashes in predicate names. Predicate declarations are of the form

PREDICATES
predicateName(argument_type1, argument_type2, ..., argument_typeN)

argument_type1, ..., argument_typeN are either standard domains or domains that you've declared in the domains section. Declaring the domain of an argument and defining the argument's type are the same thing.

The domains section is where you declare any nonstandard domains you're using for the arguments to your predicates. Domains in Prolog are like types in other languages. Visual Prolog's basic standard domains are char, byte, short, ushort, word, integer, unsigned, long, ulong, dword, real, string, and symbol; the more specialized standard domains are covered in other chapters. The basic domain declarations are of the form

DOMAINS
argument_type1, ..., argument_typeN = <standard domain>
argument_1, ..., argument_N) = <compound domain 1>;

<compound domain 2>; < ... >;

<compound domain N>;

Compound domains haven't been covered in this chapter; you'll see them in Chapter 5.

The goal section is where you put your program's internal goal; this allows the program to run independent of the development environment. With an internal goal, Visual Prolog only searches for the first solution, and the values to which variables are bound are not displayed.

If you don't use an internal goal, you'll enter an external goal in the Dialog window at run time. With an external goal, Visual Prolog searches for all solutions, and displays the values to which variables are bound.

The arity of a predicate is the number of arguments that it takes; two predicates can have the same name but different arity. You must group a predicate's different arity versions together in both the predicates and clauses sections, but different arities are treated as completely different predicates.

Rules are of the form

HEAD :- <Subgoal1>, <Subgoal2>, ..., <SubgoalN>.

For a rule to succeed, Prolog must satisfy all of its subgoals, creating a consistent set of variable bindings. If one subgoal fails, Prolog backs up and looks for alternatives to earlier subgoals, then proceeds forward with different variable values. This is called backtracking.

The :- ("if") in Prolog should not be confused with the IF used in other languages; a Prolog rule is in the form of a then/if conditional, while IF statements in other languages are in the form of an if/then conditional.

Go to next section