next up previous contents
Next: Negation as failure Up: Introduction to logic programming Previous: Turning the question around   Contents

Arithmetic

A first attempt to write a program to compute the length of a list would look as follows.

  length([],0).
  length([H,T],N) :- length(T,M), N = M+1.

If we run this program, we get a somewhat surprising result.

  ?- length([1,2,3,4],N).
  N=0+1+1+1+1

This is because = signifies unification, not equality. Thus, when the base case is reached--that is, length(T,M) with T equal to the empty list--M is assigned 0. The phrase N=M+1 unifies N with M+1 and sets N to the expression 0+1. As the program pops out of each level of recursion, an extra +1 is added, resulting in the final expression that we saw above.

To match arithmetic expressions based on their value, Prolog provides the connective is. Thus, length should be defined as follows.

  length([],0).
  length([H,T],N) :- length(T,M), N is M+1.

Now, the query length([1,2,3,4],N) behaves as we would expect.

  ?- length([1,2,3,4],N).
  N=4

Here is a more convoluted version of length.

  length(L,N) :- auxlength(L,0,N).
  auxlength([],N,N).
  auxlength({H,T],M,N) :- auxlength(T,M1,N), M1 is M+1.

Consider what happens when we ask for

  ?- length([0,1,2],N)

The goals generated are

  auxlength([0,1,2],0,N) -> auxlength([1,2],1,N) ->
  auxlength([2],2,N) -> auxlength([],3,N) -> auxlength([],3,3)

so Prolog reports back that

  N = 3.

Observe the role played by unification--the variable N is being propagated through all the subgoals and the final substitution works its way back to the original query.


next up previous contents
Next: Negation as failure Up: Introduction to logic programming Previous: Turning the question around   Contents
Madhavan Mukund 2004-04-29