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 ; noSolution
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] ; noSolution