30C. Another Example: Membership Test

Let's use equations to define function member(x, L), which is true if x belongs to list L. For example,

   member(3, [2, 6, 3, 5]) = true
   member(4, [2, 6, 3, 5]) = false

Two equations will do, one for an empty list and one for a nonempty list. Operator or is the logical or operator, the same as | | in C++. The following equations are true for all integers x and lists L.

(member.1)    member(x, [ ]) = false  
(member.2)    member(x, L) = head(L) == xormember(x, tail(L))    (when L ≠ [ ])

The first equation should be clear. The empty list does not have any members. Let's try some examples of the second equation, (member.2). According to that equation,

   member(6, [2, 4, 6, 8])
    = member(6, 2 : [4, 6, 8])
    = 6 == 2 ormember(6, [4, 6, 8])
    = false or true
    = true

(Remember the rule for hand-simulating recursive algorithms. Recursive calls are assumed to work correctly. You can do the same for checking equations.)



   member(2, [2, 4, 6, 8])
    = member(2, 2 : [4, 6, 8])
    = 2 == 2 ormember(2, [4, 6, 8])
    = true ormember(2, [4, 6, 8])
    = true

Notice that we do not need to evaluate member(2, [4, 6, 8]) because (true or x) is true regardless of what x is. This is a search problem, and the algorithm does not need to look at the entire list when the it finds what it is looking for.



   member(5, [2, 4, 6, 8])
    = member(5, 2 : [4, 6, 8])
    = 5 == 2 ormember(5, [4, 6, 8])
    = false  or false
    = false

Let's convert Equations (member.1) and (member.2) into a definition of member in C++.

  bool member(const int x, ConstList L)
  {
    if(L == NULL)
    {
      return false;
    }
    else
    {
      return x == L->head || member(x, L->tail);
    }
  }

Notice that, for both length and member, we wrote one equation for an empty list and one for a nonempty list.