32D. Summary and Caution

A loop that looks at each member of list L typically looks like this:

  for(List p = L; p != NULL; p = tail(p))
  {
    Look at head(p)
  }

We have seen how to use loops to define functions to compute the length of a list, the sum of the numbers in a list and the reversal of a list.

Be cautious about using loops with lists. Before you use a loop, make sure that your algorithm works. Suppose that we decide to use a loop to implement removeAll(x, L), which returns the list obtained from list L by removing all occurrences of x. For example, removeAll(5, [2, 5, 8, 4, 5, 3]) = [2, 8, 4, 3]. Here is an attempt to do that with loop, without planning. You already know it won't work because of the lack of planning.

  List removeAll(int x, List L)
  {
    List result = NULL;
    for(List p = L; p != NULL; p = tail(p))
    {
      if(head(L) != x)
      {
        result = cons(head(p), result);
      }
    }
    return result;
  }

You can plan or check a loop by writing a table showing the values of variables each time the loop reaches its top. Here is a such a table for the above implementation of removeAll.

 x   L  result  p 
3 [2, 3, 4, 5] [] [2, 3, 4, 5]
3 [2, 3, 4, 5] [2] [3, 4, 5]
3 [2, 3, 4, 5] [2] [4, 5]
3 [2, 3, 4, 5] [4, 2] [5]
3 [2, 3, 4, 5] [5, 4, 2] [ ]

As you can see, the loop version of removeAll returns the reversal of the list that it is supposed to return.