Processing Lists of Arbitrary Length

A real store will want to have a large inventory on-line, that is, put into a computer, so that an employee can quickly determine whether a toy is available or not. For simplicity, assume that we need <#62121#><#9742#>contains-doll?<#9742#><#62121#>, a function that checks whether the store has a <#62122#><#9743#>'<#9743#><#9744#>doll<#9744#><#62122#>. Translated into Scheme terminology, the function determines whether <#62123#><#9745#>'<#9745#><#9746#>doll<#9746#><#62123#> occurs on some list of symbols. Because we already have a rigorous definition of <#62124#><#9747#>contains-doll?<#9747#><#62124#>'s input, we turn to the contract, header, and purpose statement:
<#70962#>;; <#62125#><#9752#>contains-doll?<#9752#> <#9753#>:<#9753#> <#9754#>list-of-symbols<#9754#> <#9755#><#9755#><#9756#>-;SPMgt;<#9756#><#9757#><#9757#> <#9758#>boolean<#9758#><#62125#><#70962#>
<#70963#>;; to determine whether the symbol <#62126#><#9759#>'<#9759#><#9760#>doll<#9760#><#62126#> occurs on <#62127#><#9761#>a-list-of-symbols<#9761#><#62127#><#70963#> 
<#9762#>(define<#9762#> <#9763#>(contains-doll?<#9763#> <#9764#>a-list-of-symbols)<#9764#> <#9765#>...)<#9765#> 
Following the design recipe, we next make up some examples that illustrate <#62128#><#9769#>contains-doll?<#9769#><#62128#> purpose. First, we clearly need to determine the output for the simplest input: <#62129#><#9770#>empty<#9770#><#62129#>. Since the list does not contain any symbol, it certainly does not contain <#62130#><#9771#>'<#9771#><#9772#>doll<#9772#><#62130#>, and the answer should be <#62131#><#9773#>false<#9773#><#62131#>:
  <#9778#>(contains-doll?<#9778#> <#9779#>empty)<#9779#> 
<#9780#>=<#9780#> <#9781#>false<#9781#> 
Next, we consider lists with a single item. Here are two examples:
  <#9789#>(contains-doll?<#9789#> <#9790#>(cons<#9790#> <#9791#>'<#9791#><#9792#>ball<#9792#> <#9793#>empty))<#9793#> 
<#9794#>=<#9794#> <#9795#>false<#9795#> 
  <#9803#>(contains-doll?<#9803#> <#9804#>(cons<#9804#> <#9805#>'<#9805#><#9806#>doll<#9806#> <#9807#>empty))<#9807#>
<#9808#>=<#9808#> <#9809#>true<#9809#> 
In the first case, the answer is <#62132#><#9813#>false<#9813#><#62132#> because the single item on the list is not <#62133#><#9814#>'<#9814#><#9815#>doll<#9815#><#62133#>; in the second case, the item is <#62134#><#9816#>'<#9816#><#9817#>doll<#9817#><#62134#>, and the answer is <#62135#><#9818#>true<#9818#><#62135#>. Finally, here are two more general examples, with lists of several items:
  <#9823#>(contains-doll?<#9823#> <#9824#>(cons<#9824#> <#9825#>'<#9825#><#9826#>bow<#9826#> <#9827#>(cons<#9827#> <#9828#>'<#9828#><#9829#>arrow<#9829#> <#9830#>(cons<#9830#> <#9831#>'<#9831#><#9832#>ball<#9832#> <#9833#>empty))))<#9833#>
<#9834#>=<#9834#> <#9835#>false<#9835#> 
  <#9843#>(contains-doll?<#9843#> <#9844#>(cons<#9844#> <#9845#>'<#9845#><#9846#>arrow<#9846#> <#9847#>(cons<#9847#> <#9848#>'<#9848#><#9849#>doll<#9849#> <#9850#>(cons<#9850#> <#9851#>'<#9851#><#9852#>ball<#9852#> <#9853#>empty))))<#9853#>
<#9854#>=<#9854#> <#9855#>true<#9855#> 
Again, the answer in the first case must be <#62136#><#9859#>false<#9859#><#62136#> because the list does not contain <#62137#><#9860#>'<#9860#><#9861#>doll<#9861#><#62137#>, and in the second case it must be <#62138#><#9862#>true<#9862#><#62138#> because <#62139#><#9863#>'<#9863#><#9864#>doll<#9864#><#62139#> is one of the items on the list provided to the function. The next step is to design a function template that matches the data definition. Since the data definition for lists of symbols has two clauses, the function's body must be a <#62140#><#9865#>cond<#9865#>-expression<#62140#>. The <#62141#><#9866#>cond<#9866#>-expression<#62141#> determines which of the two kinds of lists the function received: the <#62142#><#9867#>empty<#9867#><#62142#> list or a <#62143#><#9868#>cons<#9868#><#62143#>tructed list:
<#9873#>(d<#9873#><#9874#>efine<#9874#> <#9875#>(contains-doll?<#9875#> <#9876#>a-list-of-symbols)<#9876#>
  <#9877#>(c<#9877#><#9878#>ond<#9878#> 
    <#9879#>[<#9879#><#9880#>(empty?<#9880#> <#9881#>a-list-of-symbols)<#9881#> <#9882#>...]<#9882#> 
    <#9883#>[<#9883#><#9884#>(cons?<#9884#> <#9885#>a-list-of-symbols)<#9885#> <#9886#>...]<#9886#><#9887#>))<#9887#> 
Instead of <#62144#><#9891#>(cons?<#9891#>\ <#9892#>a-list-of-symbols)<#9892#><#62144#>, we can use <#62145#><#9893#>else<#9893#><#62145#> in the second clause. We can add one more hint to the template by studying each clause of the <#62146#><#9894#>cond<#9894#>-expression<#62146#> in turn. Specifically, recall that the design recipe suggests to annotate each clause with selector expressions if the corresponding class of inputs consists of compounds. In our case, we know that <#62147#><#9895#>empty<#9895#><#62147#> does not have compounds, so there are no components. Otherwise the list is <#62148#><#9896#>cons<#9896#><#62148#>tructed from a symbol and another list of symbols, and we remind ourselves of this fact by adding <#62149#><#9897#>(first<#9897#>\ <#9898#>a-list-of-symbols)<#9898#><#62149#> and <#62150#><#9899#>(rest<#9899#>\ <#9900#>a-list-of-symbols)<#9900#><#62150#> to the template:
<#9905#>(d<#9905#><#9906#>efine<#9906#> <#9907#>(contains-doll?<#9907#> <#9908#>a-list-of-symbols)<#9908#>
  <#9909#>(c<#9909#><#9910#>ond<#9910#> 
    <#9911#>[<#9911#><#9912#>(empty?<#9912#> <#9913#>a-list-of-symbols)<#9913#> <#9914#>...]<#9914#> 
    <#9915#>[<#9915#><#9916#>else<#9916#> <#9917#>...<#9917#> <#9918#>(first<#9918#> <#9919#>a-list-of-symbols)<#9919#> <#9920#>...<#9920#> <#9921#>(rest<#9921#> <#9922#>a-list-of-symbols)<#9922#> <#9923#>...]<#9923#><#9924#>))<#9924#> 
Now that we have a template based on our design recipes for mixed and compound data, we turn to the definition of the function's body, dealing with each <#62151#><#9928#>cond<#9928#><#62151#>-clause separately. If <#62152#><#9929#>(empty?<#9929#><#9930#> <#9930#><#9931#>a-list-of-symbols)<#9931#><#62152#> is true, the input is the empty list, in which case the function must produce the result <#62153#><#9932#>false<#9932#><#62153#>. In the second case, <#62154#><#9933#>(cons?<#9933#>\ <#9934#>a-list-of-symbols)<#9934#><#62154#> is true. The annotations in the template remind us that there is a first symbol and the rest of the list. So let us consider an example that falls into this category:
<#9939#>(c<#9939#><#9940#>ons<#9940#> <#9941#>'<#9941#><#9942#>arrow<#9942#> 
  <#9943#>(con<#9943#><#9944#>s<#9944#> <#9945#>...<#9945#> 
      <#9946#>...<#9946#> <#9947#>empty)))<#9947#> 
The function, just like a human being, must clearly compare the first item with <#62155#><#9951#>'<#9951#><#9952#>doll<#9952#><#62155#>. In this example, the first symbol is <#62156#><#9953#>'<#9953#><#9954#>arrow<#9954#><#62156#> and not <#62157#><#9955#>'<#9955#><#9956#>doll<#9956#><#62157#>, so the comparison will yield <#62158#><#9957#>false<#9957#><#62158#>. If we had considered some other example instead, say,
<#9962#>(c<#9962#><#9963#>ons<#9963#> <#9964#>'<#9964#><#9965#>doll<#9965#>
  <#9966#>(con<#9966#><#9967#>s<#9967#> <#9968#>...<#9968#> 
      <#9969#>...<#9969#> <#9970#>empty)))<#9970#> 
the function would determine that the first item on the input is <#62159#><#9974#>'<#9974#><#9975#>doll<#9975#><#62159#>, and would therefore respond with <#62160#><#9976#>true<#9976#><#62160#>. All of this implies that the second line in the <#62161#><#9977#>cond<#9977#>-expression<#62161#> should contain another <#62162#><#9978#>cond<#9978#>-expression<#62162#>:
<#9983#>(d<#9983#><#9984#>efine<#9984#> <#9985#>(contains-doll?<#9985#> <#9986#>a-list-of-symbols)<#9986#>
  <#9987#>(c<#9987#><#9988#>ond<#9988#> 
    <#9989#>[<#9989#><#9990#>(empty?<#9990#> <#9991#>a-list-of-symbols)<#9991#> <#9992#>false<#9992#><#9993#>]<#9993#> 
    <#9994#>[<#9994#><#9995#>else<#9995#> <#9996#>(c<#9996#><#9997#>ond<#9997#> 
            <#9998#>[<#9998#><#9999#>(symbol=?<#9999#> <#10000#>(first<#10000#> <#10001#>a-list-of-symbols)<#10001#> <#10002#>'<#10002#><#10003#>doll)<#10003#> 
             <#10004#>true<#10004#><#10005#>]<#10005#> 
            <#10006#>[<#10006#><#10007#>else<#10007#> 
             <#10008#>...<#10008#> <#10009#>(rest<#10009#> <#10010#>a-list-of-symbols)<#10010#> <#10011#>...]<#10011#><#10012#>)]<#10012#><#10013#>))<#10013#> 
Furthermore, if the comparison of <#62163#><#10017#>(first<#10017#>\ <#10018#>a-list-of-symbols)<#10018#><#62163#> yields <#62164#><#10019#>true<#10019#><#62164#>, the function is done and produces <#62165#><#10020#>true<#10020#><#62165#>, too. If the comparison yields <#62166#><#10021#>false<#10021#><#62166#>, we are left with another list of symbols: <#62167#><#10022#>(rest<#10022#>\ <#10023#>a-list-of-symbols)<#10023#><#62167#>. Clearly, we can't know the final answer in this case, because depending on what ``...'' represents, the function must produce <#62168#><#10024#>true<#10024#><#62168#> or <#62169#><#10025#>false<#10025#><#62169#>. Put differently, if the first item is not <#62170#><#10026#>'<#10026#><#10027#>doll<#10027#><#62170#>, we need some way to check whether the rest of the list contains <#62171#><#10028#>'<#10028#><#10029#>doll<#10029#><#62171#>. Fortunately, we have just such a function: <#62172#><#10030#>contains-doll?<#10030#><#62172#>, which according to its purpose statement determines whether a list contains <#62173#><#10031#>'<#10031#><#10032#>doll<#10032#><#62173#>. The purpose statement implies that if <#62174#><#10033#>l<#10033#><#62174#> is a list of symbols, <#62175#><#10034#>(contains-doll?<#10034#>\ <#10035#>l)<#10035#><#62175#> tells us whether <#62176#><#10036#>l<#10036#><#62176#> contains the symbol <#62177#><#10037#>'<#10037#><#10038#>doll<#10038#><#62177#>. Similarly, <#62178#><#10039#>(contains-doll?<#10039#><#10040#> <#10040#><#10041#>(rest<#10041#>\ <#10042#>l))<#10042#><#62178#> determines whether the rest of <#62179#><#10043#>l<#10043#><#62179#> contains <#62180#><#10044#>'<#10044#><#10045#>doll<#10045#><#62180#>. And in the same vein, <#62181#><#10046#>(contains-doll?<#10046#>\ <#10047#>(rest<#10047#><#10048#> <#10048#><#10049#>a-list-of-symbols))<#10049#><#62181#> determines whether or not <#62182#><#10050#>'<#10050#><#10051#>doll<#10051#><#62182#> is in <#62183#><#10052#>(rest<#10052#>\ <#10053#>a-list-of-symbols)<#10053#><#62183#>, which is precisely what we need to know now. Here is the complete definition of the function:
<#10058#>(d<#10058#><#10059#>efine<#10059#> <#10060#>(contains-doll?<#10060#> <#10061#>a-list-of-symbols)<#10061#>
  <#10062#>(c<#10062#><#10063#>ond<#10063#> 
    <#10064#>[<#10064#><#10065#>(empty?<#10065#> <#10066#>a-list-of-symbols)<#10066#> <#10067#>false<#10067#><#10068#>]<#10068#> 
    <#10069#>[<#10069#><#10070#>else<#10070#> <#10071#>(c<#10071#><#10072#>ond<#10072#> 
            <#10073#>[<#10073#><#10074#>(symbol=?<#10074#> <#10075#>(first<#10075#> <#10076#>a-list-of-symbols)<#10076#> <#10077#>'<#10077#><#10078#>doll)<#10078#> <#10079#>true<#10079#><#10080#>]<#10080#> 
            <#10081#>[<#10081#><#10082#>else<#10082#> <#10083#>(contains-doll?<#10083#> <#10084#>(rest<#10084#> <#10085#>a-list-of-symbols))]<#10085#><#10086#>)]<#10086#><#10087#>))<#10087#> 
It consumes a list of symbols and determines whether or not it is empty. If it is, the result is <#62184#><#10091#>false<#10091#><#62184#>. Otherwise, the list is not empty and the result of the function depends on the first item of the list. If the first item is <#62185#><#10092#>'<#10092#><#10093#>doll<#10093#><#62185#>, the result is <#62186#><#10094#>true<#10094#><#62186#>; if not, the function's result is the result of searching the <#62187#><#10095#>rest<#10095#><#62187#> of the input list---whatever it is.
<#10098#>Exercise 9.3.1<#10098#> Use DrScheme to test the definition of <#62188#><#10100#>contains-doll?<#10100#><#62188#> on our examples:
<#10105#>empty<#10105#>
<#10106#>(cons<#10106#> <#10107#>'<#10107#><#10108#>ball<#10108#> <#10109#>empty)<#10109#> 
<#10110#>(cons<#10110#> <#10111#>'<#10111#><#10112#>arrow<#10112#> <#10113#>(cons<#10113#> <#10114#>'<#10114#><#10115#>doll<#10115#> <#10116#>empty))<#10116#> 
<#10117#>(cons<#10117#> <#10118#>'<#10118#><#10119#>bow<#10119#> <#10120#>(cons<#10120#> <#10121#>'<#10121#><#10122#>arrow<#10122#> <#10123#>(cons<#10123#> <#10124#>'<#10124#><#10125#>ball<#10125#> <#10126#>empty)))<#10126#> 
external Solution<#62189#><#62189#> <#10135#>Exercise 9.3.2<#10135#> Another way of formulating the second <#62190#><#10137#>cond<#10137#><#62190#>-clause in the function <#62191#><#10138#>contains-doll?<#10138#><#62191#> is to understand
<#10143#>(contains-doll?<#10143#> <#10144#>(rest<#10144#> <#10145#>a-list-of-symbols))<#10145#>
as a condition that evaluates to either <#62192#><#10149#>true<#10149#><#62192#> or <#62193#><#10150#>false<#10150#><#62193#>, and to combine it appropriately with the condition
<#10155#>(symbol=?<#10155#> <#10156#>(first<#10156#> <#10157#>a-list-of-symbols)<#10157#> <#10158#>'<#10158#><#10159#>doll)<#10159#>
Reformulate the definition of <#62194#><#10163#>contains-doll?<#10163#><#62194#> according to this observation.~ external Solution<#62195#><#62195#> <#10169#>Exercise 9.3.3<#10169#> Develop the function <#62196#><#10171#>contains?<#10171#><#62196#>, which consumes a symbol and a list of symbols and determines whether or not the symbol occurs on the list.~ external Solution<#62197#><#62197#>