How can a program answer a question?
Prolog is a logic programming language. You write down facts, then you ask questions, and Prolog finds the answers by searching the facts.
This matters because it is a different way to think about a program. You describe what is true. You do not write the steps. In this lesson you list the prices in a small shop and ask which items cost what.
By the end of this lesson
Note
I can state facts and ask Prolog a question about them.
Key words
| Word | What it means | Example |
|---|---|---|
| Fact | a line that says something is true | price(pen, 2). |
| Atom | a name that starts with a small letter | pen |
| Variable | a name that starts with a capital letter and stands for an answer to find | Item |
| Query | a question you ask about the facts | |
| Match | two things are the same, or can be made the same by filling in variables |
The cells students fill in are left blank in this preview.
A fact says one thing is true
Here is a shop. The line price(pen, 2). is a fact. It says "the price of a pen is 2". The word before the bracket is the name of the relation. The words inside are the things it joins. The full stop ends the fact.
Words such as pen and ruler start with a small letter. They are atoms: plain names with no value inside.
The shop file: facts, one per line
price(pen, 2).
price(ruler, 5).
price(pad, 4).
price(bag, 12).
price(tape, 4).
in_stock(pen).
in_stock(pad).
in_stock(bag).
Save the shop facts in a file
docker exec prolog sh -c "printf '%s\n' 'price(pen, 2).' 'price(ruler, 5).' 'price(pad, 4).' 'price(bag, 12).' 'price(tape, 4).' 'in_stock(pen).' 'in_stock(pad).' 'in_stock(bag).' > shop.pl"Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
Read the file back
docker exec prolog cat shop.plShown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
A query asks whether something is true
A query is a question about the facts. Prolog looks through the file for a fact that fits. If it finds one, the answer is yes. If it finds none, the answer is no.
The commands below start the Prolog program swipl. The option -g gives it the question to run. The option -t halt stops it afterwards. Everything Prolog prints is in English, whatever language this page is in.
Is a ruler priced at 5?
docker exec prolog swipl -q -g "(price(ruler, 5) -> writeln(yes) ; writeln(no))" -t halt shop.plShown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
Is a pen priced at 9?
docker exec prolog swipl -q -g "(price(pen, 9) -> writeln(yes) ; writeln(no))" -t halt shop.plShown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
A variable stands for the answer you want
Replace one atom with a name that starts with a capital letter and you have a variable. price(ruler, P) asks "what is the price of a ruler?". Prolog fills P in with every value that makes the fact true.
One query can have many answers. price(Item, 4) asks "which items cost 4?". Two facts fit, so there are two answers.
What does a ruler cost?
docker exec prolog swipl -q -g "price(ruler, P), writeln(P)" -t halt shop.plShown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
Which items cost 4?
docker exec prolog swipl -q -g "forall(price(Item, 4), writeln(Item))" -t halt shop.plShown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
Matching decides which facts fit
Prolog compares your query with each fact. They match when the name and the number of items are the same. Each item must also be equal, or be a variable that can be filled in.
If the same variable appears twice, it must get the same value both times. The table shows four tries.
Worked example: does the query match the fact?
| Query | Fact | Match? | Why |
|---|---|---|---|
| price(pad, X) | price(pad, 4) | Yes, X is 4 | pad equals pad, and X can be filled in |
| price(pad, X) | price(pen, 2) | No | pad is not pen |
| price(X, 4) | price(tape, 4) | Yes, X is tape | 4 equals 4, and X can be filled in |
| price(X) | price(pen, 2) | No | one item against two items |
The cells students fill in are left blank in this preview.
Match two terms with an equals sign
docker exec prolog swipl -q -g "pair(A, 2) = pair(pen, B), writeln(A-B)" -t haltShown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
Try it: match by hand in Python
pattern = ["price", "Item", "4"]
fact = ["price", "pad", "4"]
same = True
for i in range(len(pattern)):
word = pattern[i]
if word[0].isupper():
print(word, "can be", fact[i])
elif word != fact[i]:
same = False
print("match:", same)
# Change the fact to ["price", "pad", "5"] and press Run again.
# Then change "4" in the pattern to "5". What happens now?
A common mistake
Warning
Many people think a Prolog variable is a box you fill, like n = 5 in Python. It is not. A variable is a blank that matching fills in, and once it holds a value it keeps it for that answer. Case matters: Pen is a variable, but pen is an atom.