30D. Summary and Another Example

This chapter has looked at defining functions on lists using recursion. Recursive function definitions are based on facts, and the facts for defining a function f  on lists are equations of the form

f (A) = B   (when …)

where A and B are expressions. Since every list is either empty or nonempty, there are often two cases,

f ([ ]) = A
f (L) = B    (when L ≠ [ ])

where expression B refers to head(L) and tail(L). Sometime you need more equations to define f  on nonempty lists.

Once you have equations that you believe are true (because you have checked them on example lists), it is easy to convert those equations to a C++ definition of your function. For example, suppose that removeAll(x, L) is intended to return the list of all members of list L, but with all occurrences of x omitted. For example, removeAll(5, [2, 5, 8, 4, 5, 3]) = [2, 8, 4, 3]. Equations are as follows.

(removeAll.1)   removeAll(x, [ ]) = [ ]
(removeAll.2)   removeAll(x, L) = removeAll(x, tail(L))    (when head(L) = x)
(removeAll.3)   removeAll(x, L) = head(L) : removeAll(tail(L))    (when head(L) ≠ x)

The second equation says, among other things, that

removeAll(2, [2, 4, 2, 4]) = removeAll(2, [4, 2, 4]) = [4, 4].

The third equation says, among other things, that

removeAll(2, [5, 4, 2, 4]) = 5 : removeAll(2, [4, 2, 4]) = 5 : [4, 4] = [5, 4, 4].

Conversion to C++ is simple and direct. There are three cases, one for each equation.

  List removeAll(int x, List L)
  {
    if(L == NULL)
    {
      return NULL;
    }
    else if(x == head(L))
    {
      return removeAll(x, tail(L));
    }
    else 
    {
      remove cons(head(L), removeAll(tail(L)));
    }
  }