9.6 Practical Session
To start this session, we’ll introduce some built-in predicates for printing terms onto the screen. You should try out the following examples as we introduce them. The first predicate we want to look at is display/1 . Here are some simple examples:
?- display(loves(vincent,mia)). loves(vincent, mia) yes ?- display('jules eats a big kahuna burger'). jules eats a big kahuna burger yes
But the really important point about display/1 , as the following examples demonstrate, is that it prints Prolog’s internal representation of terms to the screen:
?- display(2+3+4).
+(+(2, 3), 4)
yes
This property of display/1 makes it a very useful tool for learning how operators work in Prolog. So, before going on, try the following queries. Make sure you understand why Prolog answers the way it does.
?- display([a,b,c]). ?- display(3 is 4 + 5 / 3). ?- display(3 is (4 + 5) / 3). ?- display((a:-b,c,d)). ?- display(a:-b,c,d).
So display/1 is useful when we want to look at the internal representation of terms in operator notation. But often we would prefer to see the user-friendly notation instead. For example, when reading lists it is usually more pleasant to see [a,b,c] rather than .(a.(b.(c,[]))) . The built-in predicate write/1 lets us view terms like this. This predicate takes a term and prints it to the screen in the user-friendly notation.
?- write(2+3+4). 2+3+4 yes ?- write(+(2,3)). 2+3 yes ?- write([a,b,c]). [a, b, c] yes ?- write(.(a,.(b,[]))). [a, b] yes
And here is what happens when the term to be written contains variables:
?- write(X). _G204 X = _G204 yes ?- X = a, write(X). a X = a yes
The following example shows what happens when you give two write/1 commands one after the other:
?- write(a),write(b).
ab
yes
That is, Prolog just executes one after the other without putting any space in between the output of the two commands. Of course, you can get Prolog to print space by telling it to write the term ’ ’ :
?- write(a),write(' '),write(b).
a b
yes
And if you want more than one space, for example five blanks, you can tell Prolog to write ’ ’ .
?- write(a),write(' '),write(b).
a b
yes
Another way of printing spaces is by using the predicate tab/1 . This takes a number as argument and then prints that number of spaces:
?- write(a),tab(5),write(b).
a b
yes
Another predicate useful for formatting is nl . This tells Prolog to make a line-break and to go on printing on the next line.
?- write(a),nl,write(b).
a
b
yes
Time to apply what you have just learned. In the last chapter we saw how extra arguments in DCGs could be used to build parse trees. For example, to the query
s(T,[a,man,shoots,a,woman],[])
Prolog would answer
s(np(det(a),n(man)),vp(v(shoots),np(det(a),n(woman)))).
This term is a representation of the parse tree, but it is not a very readable representation. It would be nicer if Prolog printed something like the following (this style of printing is usually called pretty printing):
s( np( det(a) n(man)) vp( v(shoots) np( det(a) n(woman))))
Write a predicate pptree/1 that takes a complex term representing a tree as its argument and prints the tree in a more readable form.
Time to practice writing operator definitions. In the practical session of Chapter 7 , you were asked to write a DCG generating propositional logic formulas. The input you had to use was a bit awkward though. The formula ¬ ( p → q ) had to be represented as [not, ’(’, p, implies, q, ’)’] . Now that you know about operators, you can do things rather more neatly. Write operator definitions for not , and , or , and implies , so that Prolog accepts (and correctly brackets) propositional logic formulas. Use display/1 to check your code. It should yield the following kinds of response:
?- display(not(p implies q)). not(implies(p,q)). yes ?- display(not p implies q). implies(not(p),q) yes