General
Material
Lecture 1
Lecture 2
Lecture 3
Lecture 4
Lecture 5

Programming with DCGs

As we saw yesterday, the --> notation is just syntactic sugar for an ordinary Prolog rule. Therefore, it should not come as too much of a surprise that we can also add calls to any Prolog predicate whatsoever to the right hand side of a DCG rule.

These extra goals can be written anywhere on the right side of a DCG rule, but must stand between curly brackets. When Prolog encounters such curly brackets while translating a DCG into its internal representation, it just takes the extra goals specified between the curly brackets over into the translation.

Here is an example what such rules look like:

kanga(V,Q) --> roo(V),{marsupial(V,R,Q)},jumps(R,Q).
    
And the internal representation of this rule is something like
kanga(V,Q,In,Out) :- 
              roo(V,In,X1),
              marsupial(V,R,Q),
              jumps(R,Q,X1,Out).
    

This possibility of adding arbitrary Prolog goals to the right hand side of DCG rules, makes DCGs very very powerful (in fact, we can do anything that we can do in Prolog). It is not used much for linguistic applications, but some people like to use DCGs with additional goals to program. Here is, for instance, a DCG which calculates the length of it's input list.

list_length(0) --> [].
list_length(Length) --> [_], 
                	list_length(RestLength), 
	                {Length is RestLength + 1}.
    
If the list is empty, the length is 0. Otherwise, take away one element, calculate the length of the rest, and add 1 to it. For example,
?- list_length(L,[a,b,c],[]).
L = 3 ;
no
?- list_length(L,[],[]).
L = 0 ;
no
    

Write a predicate sum/3, which takes a list of numbers and sums them up. Write this predicate as a DCG. Hint: The predicate sum has 3 arguments: the 2 arguments which Prolog automatically adds to DCG rules and 1 extra argument to compute the sum in. The predicate should behave as follows:

?- sum(Sum,[1,1,2,2],[]).
Sum = 6 ;
no
    
Solution

The flatten predicate that appeared in the exercises of day 3 (here and here) can also be written as a DCG. This DCG also has one extra argument which is where the original (non-flattened) list goes. So, the interaction with this predicate would, for example, look like this:

?- flatten_dcg([a,[[b],c,[x]]], R, []).
R = [a, b, c, x] ;
no
    
Solution

Back to the practical session of day 5.