Equality and Testing

Many of the functions we designed produce lists. When we test these functions, we must compare their result with the predicted value, which are both lists. Comparing lists by hand is tedious and error-prone. Let's develop a function that consumes two lists of numbers and determines whether they are equal:
<#71153#>;; <#64368#><#21705#>list=?<#21705#> <#21706#>:<#21706#> <#21707#>list-of-numbers<#21707#> <#21708#>list-of-numbers<#21708#> <#21709#><#21709#><#21710#>-;SPMgt;<#21710#><#21711#><#21711#> <#21712#>boolean<#21712#><#64368#><#71153#>
<#71154#>;; to determine whether <#64369#><#21713#>a-list<#21713#><#64369#> and <#64370#><#21714#>another-list<#21714#><#64370#> <#71154#> 
<#21715#>;; contain the same numbers in the same order<#21715#> 
<#21716#>(define<#21716#> <#21717#>(list=?<#21717#> <#21718#>a-list<#21718#> <#21719#>another-list)<#21719#> <#21720#>...)<#21720#> 
The purpose statement refines our general claim and reminds us that, for example, shoppers may consider two lists equal if they contain the same items, regardless of the order, but programmers are more specific and include the order in the comparison. The contract and the purpose statement also show that <#64371#><#21724#>list=?<#21724#><#64371#> is a function that processes two complex values, and indeed, it is an interesting case study. Comparing two lists means to look at each item in both lists. This rules out designing <#64372#><#21725#>list=?<#21725#><#64372#> along the lines of <#64373#><#21726#>replace-eol-with<#21726#><#64373#> in section~#sectwoinputscase1#21727>. At first glance, there is also no connection between the two lists, which suggests that we should use the modified design recipe. Let's start with the table:

#tabular21729#

It has four cells, which implies that we need (at least) four tests and four <#64378#><#21741#>cond<#21741#><#64378#>-clauses in the template. Here are five tests:

  <#21746#>(list=?<#21746#> <#21747#>empty<#21747#> <#21748#>empty)<#21748#> 
<#21749#>=<#21749#> <#21750#>true<#21750#> 
  <#21758#>(list=?<#21758#> <#21759#>empty<#21759#> <#21760#>(cons<#21760#> <#21761#>1<#21761#> <#21762#>empty))<#21762#>
<#21763#>=<#21763#> <#21764#>false<#21764#> 
  <#21772#>(list=?<#21772#> <#21773#>(cons<#21773#> <#21774#>1<#21774#> <#21775#>empty)<#21775#> <#21776#>empty)<#21776#>
<#21777#>=<#21777#> <#21778#>false<#21778#> 
  <#21786#>(list=?<#21786#> <#21787#>(cons<#21787#> <#21788#>1<#21788#> <#21789#>(cons<#21789#> <#21790#>2<#21790#> <#21791#>(cons<#21791#> <#21792#>3<#21792#> <#21793#>empty)))<#21793#> 
          <#21794#>(cons<#21794#> <#21795#>1<#21795#> <#21796#>(cons<#21796#> <#21797#>2<#21797#> <#21798#>(cons<#21798#> <#21799#>3<#21799#> <#21800#>empty))))<#21800#> 
<#21801#>=<#21801#> <#21802#>true<#21802#> 
  <#21810#>(list=?<#21810#> <#21811#>(cons<#21811#> <#21812#>1<#21812#> <#21813#>(cons<#21813#> <#21814#>2<#21814#> <#21815#>(cons<#21815#> <#21816#>3<#21816#> <#21817#>empty)))<#21817#> 
          <#21818#>(cons<#21818#> <#21819#>1<#21819#> <#21820#>(cons<#21820#> <#21821#>3<#21821#> <#21822#>empty)))<#21822#> 
<#21823#>=<#21823#> <#21824#>false<#21824#> 
The second and third show that <#64379#><#21828#>list=?<#21828#><#64379#> must deal with its arguments in a symmetric fashion. The last two show how <#64380#><#21829#>list=?<#21829#><#64380#> can produce <#64381#><#21830#>true<#21830#><#64381#> and <#64382#><#21831#>false<#21831#><#64382#>. Three of the template's four <#64383#><#21832#>cond<#21832#><#64383#>-clauses contain selector expressions and one contains natural recursions:
<#21837#>(d<#21837#><#21838#>efine<#21838#> <#21839#>(list=?<#21839#> <#21840#>a-list<#21840#> <#21841#>another-list)<#21841#>
  <#21842#>(c<#21842#><#21843#>ond<#21843#> 
    <#21844#>[<#21844#><#21845#>(and<#21845#> <#21846#>(empty?<#21846#> <#21847#>a-list)<#21847#> <#21848#>(empty?<#21848#> <#21849#>another-list))<#21849#> <#21850#>...]<#21850#> 
    <#21851#>[<#21851#><#21852#>(and<#21852#> <#21853#>(cons?<#21853#> <#21854#>a-list)<#21854#> <#21855#>(empty?<#21855#> <#21856#>another-list))<#21856#> 
     <#21857#>...<#21857#> <#21858#>(first<#21858#> <#21859#>a-list)<#21859#> <#21860#>...<#21860#> <#21861#>(rest<#21861#> <#21862#>a-list)<#21862#> <#21863#>...]<#21863#> 
    <#21864#>[<#21864#><#21865#>(and<#21865#> <#21866#>(empty?<#21866#> <#21867#>a-list)<#21867#> <#21868#>(cons?<#21868#> <#21869#>another-list))<#21869#> 
    <#21870#>...<#21870#> <#21871#>(first<#21871#> <#21872#>another-list)<#21872#> <#21873#>...<#21873#> <#21874#>(rest<#21874#> <#21875#>another-list)<#21875#> <#21876#>...]<#21876#> 
    <#21877#>[<#21877#><#21878#>(and<#21878#> <#21879#>(cons?<#21879#> <#21880#>a-list)<#21880#> <#21881#>(cons?<#21881#> <#21882#>another-list))<#21882#> 
     <#21883#>...<#21883#> <#21884#>(first<#21884#> <#21885#>a-list)<#21885#> <#21886#>...<#21886#> <#21887#>(first<#21887#> <#21888#>another-list)<#21888#> <#21889#>...<#21889#> 
     <#21890#>...<#21890#> <#21891#>(list=?<#21891#> <#21892#>(rest<#21892#> <#21893#>a-list)<#21893#> <#21894#>(rest<#21894#> <#21895#>another-list))<#21895#> <#21896#>...<#21896#> 
     <#21897#>...<#21897#> <#21898#>(list=?<#21898#> <#21899#>a-list<#21899#> <#21900#>(rest<#21900#> <#21901#>another-list))<#21901#> <#21902#>...<#21902#> 
     <#21903#>...<#21903#> <#21904#>(list=?<#21904#> <#21905#>(rest<#21905#> <#21906#>a-list)<#21906#> <#21907#>another-list)<#21907#> <#21908#>...]<#21908#><#21909#>))<#21909#> 
There are three natural recursions in the fourth clause because we can pair the two selector expressions and we can pair each parameter with one selector expression. From the template to the complete definition is only a small step. Two lists can only contain the same items if they are both empty or <#64384#><#21913#>cons<#21913#><#64384#>tructed. This immediately implies <#64385#><#21914#>true<#21914#><#64385#> as the answer for the first <#64386#><#21915#>clause<#21915#><#64386#> and <#64387#><#21916#>false<#21916#><#64387#> for the next two. In the last clause, we have two numbers, the first of both lists, and three natural recursions. We must compare the two numbers. Furthermore, <#64388#><#21917#>(list=?<#21917#>\ <#21918#>(rest<#21918#>\ <#21919#>a-list)<#21919#>\ <#21920#>(rest<#21920#>\ <#21921#>another-list))<#21921#><#64388#> computes whether the rests of the two lists are equal. The two lists are equal if, and only if, both conditions hold, which means we must combine them with an <#64389#><#21922#>and<#21922#><#64389#>:
<#21927#>(d<#21927#><#21928#>efine<#21928#> <#21929#>(list=?<#21929#> <#21930#>a-list<#21930#> <#21931#>another-list)<#21931#>
  <#21932#>(c<#21932#><#21933#>ond<#21933#> 
    <#21934#>[<#21934#><#21935#>(and<#21935#> <#21936#>(empty?<#21936#> <#21937#>a-list)<#21937#> <#21938#>(empty?<#21938#> <#21939#>another-list))<#21939#> <#21940#>true]<#21940#> 
    <#21941#>[<#21941#><#21942#>(and<#21942#> <#21943#>(cons?<#21943#> <#21944#>a-list)<#21944#> <#21945#>(empty?<#21945#> <#21946#>another-list))<#21946#> <#21947#>false]<#21947#> 
    <#21948#>[<#21948#><#21949#>(and<#21949#> <#21950#>(empty?<#21950#> <#21951#>a-list)<#21951#> <#21952#>(cons?<#21952#> <#21953#>another-list))<#21953#> <#21954#>false]<#21954#> 
    <#21955#>[<#21955#><#21956#>(and<#21956#> <#21957#>(cons?<#21957#> <#21958#>a-list)<#21958#> <#21959#>(cons?<#21959#> <#21960#>another-list))<#21960#> 
     <#21961#>(and<#21961#> <#21962#>(=<#21962#> <#21963#>(first<#21963#> <#21964#>a-list)<#21964#> <#21965#>(first<#21965#> <#21966#>another-list))<#21966#> 
          <#21967#>(list=?<#21967#> <#21968#>(rest<#21968#> <#21969#>a-list)<#21969#> <#21970#>(rest<#21970#> <#21971#>another-list)))]<#21971#><#21972#>))<#21972#> 
The other two natural recursions play no role. Let us now take a second look at the connection between the two parameters. The first development suggests that the second parameter must have the same shape as the first one, if the two lists are to be equal. Put differently, we could develop the function based on the structure of the first parameter and check structure of the other one as needed. The first parameter is a list of numbers, so we can reuse the template for list-processing functions:
<#21980#>(d<#21980#><#21981#>efine<#21981#> <#21982#>(list=?<#21982#> <#21983#>a-list<#21983#> <#21984#>another-list)<#21984#>
  <#21985#>(c<#21985#><#21986#>ond<#21986#> 
    <#21987#>[<#21987#><#21988#>(empty?<#21988#> <#21989#>a-list)<#21989#> <#21990#>...]<#21990#> 
    <#21991#>[<#21991#><#21992#>(cons?<#21992#> <#21993#>a-list)<#21993#> 
     <#21994#>...<#21994#> <#21995#>(first<#21995#> <#21996#>a-list)<#21996#> <#21997#>...<#21997#> <#21998#>(first<#21998#> <#21999#>another-list)<#21999#> <#22000#>...<#22000#> 
     <#22001#>...<#22001#> <#22002#>(list=?<#22002#> <#22003#>(rest<#22003#> <#22004#>a-list)<#22004#> <#22005#>(rest<#22005#> <#22006#>another-list))<#22006#> <#22007#>...]<#22007#><#22008#>))<#22008#> 
The only difference is that the second clause processes the second parameter in the same way as the first one. This mimics the development of <#71155#><#22012#>hours<#22012#><#64390#><#22013#><#22013#><#22014#>-;SPMgt;<#22014#><#22015#><#22015#><#64390#><#22016#>wages<#22016#><#71155#> in section~#sectwoinputscase2#22017>. Filling the gaps in this template is more difficult than for the first development of <#64391#><#22018#>list=?<#22018#><#64391#>. If <#64392#><#22019#>a-list<#22019#><#64392#> is <#64393#><#22020#>empty<#22020#><#64393#>, the answer depends on <#64394#><#22021#>another-list<#22021#><#64394#>. As the examples show, the answer is <#64395#><#22022#>true<#22022#><#64395#> if, and only if, <#64396#><#22023#>another-list<#22023#><#64396#> is also <#64397#><#22024#>empty<#22024#><#64397#>. Translated into Scheme this means that the answer in the first <#64398#><#22025#>cond<#22025#><#64398#>-clause is <#64399#><#22026#>(empty?<#22026#>\ <#22027#>another-list)<#22027#><#64399#>. If <#64400#><#22028#>a-list<#22028#><#64400#> is not empty, the template suggests that we compute the answer from
  1. <#64401#><#22030#>(first<#22030#>\ <#22031#>a-list)<#22031#><#64401#>, the first number of <#64402#><#22032#>a-list<#22032#><#64402#>;
  2. <#64403#><#22033#>(first<#22033#>\ <#22034#>another-list)<#22034#><#64403#>, the first number on <#64404#><#22035#>another-list<#22035#><#64404#>; and
  3. <#64405#><#22036#>(list=?<#22036#>\ <#22037#>(rest<#22037#>\ <#22038#>a-list)<#22038#>\ <#22039#>(rest<#22039#>\ <#22040#>another-list))<#22040#><#64405#>, which determines whether the rests of the two lists are equal.
Given the purpose of the function and the examples, we now simply compare <#64406#><#22042#>(first<#22042#>\ <#22043#>a-list)<#22043#><#64406#> and <#64407#><#22044#>(first<#22044#>\ <#22045#>another-list)<#22045#><#64407#> and combine the result with the natural recursion in an <#64408#><#22046#>and<#22046#>-expression<#64408#>:
<#22051#>(and<#22051#> <#22052#>(=<#22052#> <#22053#>(first<#22053#> <#22054#>a-list)<#22054#> <#22055#>(first<#22055#> <#22056#>another-list))<#22056#>
     <#22057#>(list=?<#22057#> <#22058#>(rest<#22058#> <#22059#>a-list)<#22059#> <#22060#>(rest<#22060#> <#22061#>another-list)))<#22061#> 
While this step appears to be simple and straightforward, the result is an improper definition. The purpose of spelling out the conditions in a <#64409#><#22065#>cond<#22065#>-expression<#64409#> is to ensure that all selector expressions are appropriate. Nothing in the specification of <#64410#><#22066#>list=?<#22066#><#64410#>, however, suggests that <#64411#><#22067#>another-list<#22067#><#64411#> is <#64412#><#22068#>cons<#22068#><#64412#>tructed if <#64413#><#22069#>a-list<#22069#><#64413#> is <#64414#><#22070#>cons<#22070#><#64414#>tructed. We can overcome this problem with an additional condition:
<#22075#>(d<#22075#><#22076#>efine<#22076#> <#22077#>(list=?<#22077#> <#22078#>a-list<#22078#> <#22079#>another-list)<#22079#>
  <#22080#>(c<#22080#><#22081#>ond<#22081#> 
    <#22082#>[<#22082#><#22083#>(empty?<#22083#> <#22084#>a-list)<#22084#> <#22085#>(empty?<#22085#> <#22086#>another-list)]<#22086#> 
    <#22087#>[<#22087#><#22088#>(cons?<#22088#> <#22089#>a-list)<#22089#> 
     <#22090#>(and<#22090#> <#22091#>(cons?<#22091#> <#22092#>another-list)<#22092#> 
          <#22093#>(and<#22093#> <#22094#>(=<#22094#> <#22095#>(first<#22095#> <#22096#>a-list)<#22096#> <#22097#>(first<#22097#> <#22098#>another-list))<#22098#> 
               <#22099#>(list=?<#22099#> <#22100#>(rest<#22100#> <#22101#>a-list)<#22101#> <#22102#>(rest<#22102#> <#22103#>another-list))))]<#22103#><#22104#>))<#22104#> 
The additional condition is <#64415#><#22108#>(cons?<#22108#>\ <#22109#>another-list)<#22109#><#64415#>, which means that <#64416#><#22110#>list=?<#22110#><#64416#> produces <#64417#><#22111#>false<#22111#><#64417#> if <#64418#><#22112#>(cons?<#22112#>\ <#22113#>a-list)<#22113#><#64418#> is true and <#64419#><#22114#>(cons?<#22114#>\ <#22115#>another-list)<#22115#><#64419#> is empty. As the examples show, this is the desired outcome. In summary, <#64420#><#22116#>list=?<#22116#><#64420#> shows that, on occasion, we can use more than one design recipe to develop a function. The outcomes are different, though closely related; indeed, we could prove that the two always produce the same results for the same inputs. Also, the second development benefited from the first one.
<#22119#>Exercise 17.8.1<#22119#> Test both versions of <#64421#><#22121#>list=?<#22121#><#64421#>.~ external Solution<#64422#><#64422#> <#22127#>Exercise 17.8.2<#22127#> Simplify the first version of <#64423#><#22129#>list=?<#22129#><#64423#>. Simplifying means to merge neighboring <#64424#><#22130#>cond<#22130#><#64424#>-clauses with the same result by combining their conditions in an <#64425#><#22131#>or<#22131#>-expression<#64425#>; to switch <#64426#><#22132#>cond<#22132#><#64426#>-clauses; or to use <#64427#><#22133#>else<#22133#><#64427#> in the last clause of the final version.~ external Solution<#64428#><#64428#> <#22139#>Exercise 17.8.3<#22139#> Develop <#64429#><#22141#>sym-list=?<#22141#><#64429#>. The function determines whether two lists of symbols are equal.~ external Solution<#64430#><#64430#> <#22147#>Exercise 17.8.4<#22147#> Develop <#64431#><#22149#>contains-same-numbers<#22149#><#64431#>. The function determines whether two lists of numbers contain the numbers, regardless of the ordering. Thus, for example,
<#22154#>(contains-same-numbers<#22154#> <#22155#>(list<#22155#> <#22156#>1<#22156#> <#22157#>2<#22157#> <#22158#>3)<#22158#> <#22159#>(list<#22159#> <#22160#>3<#22160#> <#22161#>2<#22161#> <#22162#>1))<#22162#>
evaluates to <#64432#><#22166#>true<#22166#><#64432#>.~ external Solution<#64433#><#64433#> <#22172#>Exercise 17.8.5<#22172#> The class of numbers, symbols, and booleans are sometimes called atoms:
An <#64436#><#22177#>atom<#22177#><#64436#> is either
  1. a number
  2. a boolean
  3. a symbol
Develop the function <#64437#><#22181#>list-equal?<#22181#><#64437#>, which consumes two lists of atoms and determines whether they are equal.~ external Solution<#64438#><#64438#>
A comparison between the two versions of <#64439#><#22189#>list=?<#22189#><#64439#> suggests that the second one is easier to understand than the first. It says that two compound values are equal if the second is made from the same constructor and the components are equal. In general, this idea is a good guide for the development of other equality functions. Let's look at an equality function for simple Web pages to confirm this conjecture:
<#71157#>;; <#64440#><#22194#>web=?<#22194#> <#22195#>:<#22195#> <#22196#>web-page<#22196#> <#22197#>web-page<#22197#> <#22198#><#22198#><#22199#>-;SPMgt;<#22199#><#22200#><#22200#> <#22201#>boolean<#22201#><#64440#><#71157#>
<#71158#>;; to determine whether <#64441#><#22202#>a-wp<#22202#><#64441#> and <#64442#><#22203#>another-wp<#22203#><#64442#> have the same tree shape<#71158#> 
<#22204#>;; and contain the same symbols in the same order<#22204#> 
<#22205#>(define<#22205#> <#22206#>(web=?<#22206#> <#22207#>a-wp<#22207#> <#22208#>another-wp)<#22208#> <#22209#>...)<#22209#> 
Recall the data definition for simple Web pages:
A <#64443#><#22214#>Web page<#22214#><#64443#> (<#64444#><#22215#>WP<#22215#><#64444#>) is either
  1. <#64445#><#22217#>empty<#22217#><#64445#>;
  2. <#64446#><#22218#>(cons<#22218#>\ <#22219#>s<#22219#>\ <#22220#>wp)<#22220#><#64446#>
    where <#64447#><#22221#>s<#22221#><#64447#> is a symbol and <#64448#><#22222#>wp<#22222#><#64448#> is a Web page; or
  3. <#64449#><#22223#>(cons<#22223#>\ <#22224#>ewp<#22224#>\ <#22225#>wp)<#22225#><#64449#>
    where both <#64450#><#22226#>ewp<#22226#><#64450#> and <#64451#><#22227#>wp<#22227#><#64451#> are Web pages.
The data definition has three clauses, which means that if we were to develop <#64452#><#22230#>web=?<#22230#><#64452#> with the modified design recipe, we would need to study nine cases. By using the insight gained from the development of <#64453#><#22231#>list=?<#22231#><#64453#> instead, we can start from the plain web-processing template:
<#22236#>(d<#22236#><#22237#>efine<#22237#> <#22238#>(web=?<#22238#> <#22239#>a-wp<#22239#> <#22240#>another-wp)<#22240#>
  <#22241#>(c<#22241#><#22242#>ond<#22242#> 
    <#22243#>[<#22243#><#22244#>(empty?<#22244#> <#22245#>a-wp)<#22245#> <#22246#>...]<#22246#> 
    <#22247#>[<#22247#><#22248#>(symbol?<#22248#> <#22249#>(first<#22249#> <#22250#>a-wp))<#22250#> 
     <#22251#>...<#22251#> <#22252#>(first<#22252#> <#22253#>a-wp)<#22253#> <#22254#>...<#22254#> <#22255#>(first<#22255#> <#22256#>another-wp)<#22256#> <#22257#>...<#22257#> 
     <#22258#>...<#22258#> <#22259#>(web=?<#22259#> <#22260#>(rest<#22260#> <#22261#>a-wp)<#22261#> <#22262#>(rest<#22262#> <#22263#>another-wp))<#22263#> <#22264#>...]<#22264#> 
    <#22265#>[<#22265#><#22266#>else<#22266#> 
     <#22267#>...<#22267#> <#22268#>(web=?<#22268#> <#22269#>(first<#22269#> <#22270#>a-wp)<#22270#> <#22271#>(first<#22271#> <#22272#>another-wp))<#22272#> <#22273#>...<#22273#> 
     <#22274#>...<#22274#> <#22275#>(web=?<#22275#> <#22276#>(rest<#22276#> <#22277#>a-wp)<#22277#> <#22278#>(rest<#22278#> <#22279#>another-wp))<#22279#> <#22280#>...]<#22280#><#22281#>))<#22281#> 
In the second <#64454#><#22285#>cond<#22285#><#64454#>-clause, we follow the example of <#71159#><#22286#>hours<#22286#><#64455#><#22287#><#22287#><#22288#>-;SPMgt;<#22288#><#22289#><#22289#><#64455#><#22290#>wages<#22290#><#71159#> and <#64456#><#22291#>list=?<#22291#><#64456#> again. That is, we say that <#64457#><#22292#>another-wp<#22292#><#64457#> must have the same shape as <#64458#><#22293#>a-wp<#22293#><#64458#> if it is to be equal and process the two pages in an analogous manner. The reasoning for the third clause is similar. As we refine this template into a full definition now, we must again add conditions on <#64459#><#22294#>another-wp<#22294#><#64459#> to ensure that the selector expressions are justified:
<#22299#>(d<#22299#><#22300#>efine<#22300#> <#22301#>(web=?<#22301#> <#22302#>a-wp<#22302#> <#22303#>another-wp)<#22303#>
  <#22304#>(c<#22304#><#22305#>ond<#22305#> 
    <#22306#>[<#22306#><#22307#>(empty?<#22307#> <#22308#>a-wp)<#22308#> <#22309#>(empty?<#22309#> <#22310#>another-wp)]<#22310#> 
    <#22311#>[<#22311#><#22312#>(symbol?<#22312#> <#22313#>(first<#22313#> <#22314#>a-wp))<#22314#> 
     <#22315#>(and<#22315#> <#22316#>(and<#22316#> <#22317#>(cons?<#22317#> <#22318#>another-wp)<#22318#> <#22319#>(symbol?<#22319#> <#22320#>(first<#22320#> <#22321#>another-wp)))<#22321#> 
          <#22322#>(and<#22322#> <#22323#>(symbol=?<#22323#> <#22324#>(first<#22324#> <#22325#>a-wp)<#22325#> <#22326#>(first<#22326#> <#22327#>another-wp))<#22327#> 
               <#22328#>(web=?<#22328#> <#22329#>(rest<#22329#> <#22330#>a-wp)<#22330#> <#22331#>(rest<#22331#> <#22332#>another-wp))))]<#22332#> 
    <#22333#>[<#22333#><#22334#>else<#22334#> 
     <#22335#>(and<#22335#> <#22336#>(and<#22336#> <#22337#>(cons?<#22337#> <#22338#>another-wp)<#22338#> <#22339#>(list?<#22339#> <#22340#>(first<#22340#> <#22341#>another-wp)))<#22341#> 
          <#22342#>(and<#22342#> <#22343#>(web=?<#22343#> <#22344#>(first<#22344#> <#22345#>a-wp)<#22345#> <#22346#>(first<#22346#> <#22347#>another-wp))<#22347#> 
               <#22348#>(web=?<#22348#> <#22349#>(rest<#22349#> <#22350#>a-wp)<#22350#> <#22351#>(rest<#22351#> <#22352#>another-wp))))]<#22352#><#22353#>))<#22353#> 
In particular, we must ensure in the second and third clause that <#64460#><#22357#>another-wp<#22357#><#64460#> is a <#64461#><#22358#>cons<#22358#><#64461#>tructed list and that the first item is a symbol or a list, respectively. Otherwise the function is analogous to <#64462#><#22359#>list=?<#22359#><#64462#> and works in the same way.
<#22362#>Exercise 17.8.6<#22362#> Draw the table based on the data definition for simple Web pages. Develop (at least) one example for each of the nine cases. Test <#64463#><#22364#>web=?<#22364#><#64463#> with these examples.~ external Solution<#64464#><#64464#> <#22370#>Exercise 17.8.7<#22370#> Develop the function <#64465#><#22372#>posn=?<#22372#><#64465#>, which consumes two binary <#64466#><#22373#>posn<#22373#><#64466#> structures and determines whether they are equal.~ external Solution<#64467#><#64467#> <#22379#>Exercise 17.8.8<#22379#> Develop the function <#64468#><#22381#>tree=?<#22381#><#64468#>, which consumes two binary trees and determines whether they are equal.~ external Solution<#64469#><#64469#> <#22387#>Exercise 17.8.9<#22387#> Consider the following two, mutually recursive data definitions:
A <#64470#><#22390#>Slist<#22390#><#64470#> is either
  1. <#64471#><#22392#>empty<#22392#><#64471#>
  2. <#64472#><#22393#>(cons<#22393#>\ <#22394#>s<#22394#>\ <#22395#>sl)<#22395#><#64472#> where <#64473#><#22396#>s<#22396#><#64473#> is a <#64474#><#22397#>Sexpr<#22397#><#64474#> and <#64475#><#22398#>sl<#22398#><#64475#> is a <#64476#><#22399#>Slist<#22399#><#64476#>.

A <#64477#><#22401#>Sexpr<#22401#><#64477#> is either

  1. a number
  2. a boolean
  3. a symbol
  4. a <#64478#><#22403#>Slist<#22403#><#64478#>

Develop the function <#64479#><#22406#>Slist=?<#22406#><#64479#>, which consumes two <#64480#><#22407#>Slists<#22407#><#64480#> and determines whether they are equal. Like lists of numbers, two Slists are equal is they contain the same item at analogous positions.~ external Solution<#64481#><#64481#>
Now that we have explored the idea of equality of values, we can return to the original motivation of the section: testing functions. Suppose we wish to test <#71160#><#22415#>hours<#22415#><#64482#><#22416#><#22416#><#22417#>-;SPMgt;<#22417#><#22418#><#22418#><#64482#><#22419#>wages<#22419#><#71160#> from section~#sectwoinputscase2#22420>:
  <#22425#>(<#22425#><#22426#>hours<#22426#><#64483#><#22427#><#22427#><#22428#>-;SPMgt;<#22428#><#22429#><#22429#><#64483#><#22430#>wages<#22430#> <#22431#>(cons<#22431#> <#22432#>5.65<#22432#> <#22433#>(cons<#22433#> <#22434#>8.75<#22434#> <#22435#>empty))<#22435#> 
                      <#22436#>(cons<#22436#> <#22437#>40<#22437#> <#22438#>(cons<#22438#> <#22439#>30<#22439#> <#22440#>empty)))<#22440#> 
<#22441#>=<#22441#> <#22442#>(cons<#22442#> <#22443#>226.0<#22443#> <#22444#>(cons<#22444#> <#22445#>262.5<#22445#> <#22446#>empty))<#22446#> 
If we just type in the application into <#22450#>Interactions<#22450#> window or add it to the bottom of the <#22451#>Definitions<#22451#> window, we must compare the result and the predicted value by inspection. For short lists, like the ones above, this is feasible; for long lists, deep Web pages, or other large compound data, manual inspection is error-prone. Using equality functions like <#64484#><#22452#>list=?<#22452#><#64484#>, we can greatly reduce the need for manual inspection of test results. In our running example, we can add the expression
<#22457#>(l<#22457#><#22458#>ist=?<#22458#> 
  <#22459#>(<#22459#><#22460#>hours<#22460#><#64485#><#22461#><#22461#><#22462#>-;SPMgt;<#22462#><#22463#><#22463#><#64485#><#22464#>wages<#22464#> <#22465#>(cons<#22465#> <#22466#>5.65<#22466#> <#22467#>(cons<#22467#> <#22468#>8.75<#22468#> <#22469#>empty))<#22469#> 
                      <#22470#>(cons<#22470#> <#22471#>40<#22471#> <#22472#>(cons<#22472#> <#22473#>30<#22473#> <#22474#>empty)))<#22474#> 
  <#22475#>(cons<#22475#> <#22476#>226.0<#22476#> <#22477#>(cons<#22477#> <#22478#>262.5<#22478#> <#22479#>empty)))<#22479#> 
to the bottom of the <#22483#>Definitions<#22483#> window. When we click the <#22484#>Execute<#22484#> button now, we just need to make sure that all test cases produce <#64486#><#22485#>true<#22485#><#64486#> as their results are displayed in the <#22486#>Interactions<#22486#> window.
<#72226#>;; <#71161#><#22491#>test-hours<#22491#><#64487#><#22492#><#22492#><#22493#>-;SPMgt;<#22493#><#22494#><#22494#><#64487#><#22495#>wages<#22495#> <#22496#>:<#22496#> <#22497#>list-of-numbers<#22497#> <#22498#>list-of-numbers<#22498#> <#22499#>list-of-numbers<#22499#> <#22500#><#22500#><#22501#>-;SPMgt;<#22501#><#22502#><#22502#> <#22503#>test-result<#22503#><#71161#><#72226#>
<#72227#>;; to test <#71162#><#22504#>hours<#22504#><#64488#><#22505#><#22505#><#22506#>-;SPMgt;<#22506#><#22507#><#22507#><#64488#><#22508#>wages<#22508#><#71162#><#72227#> 
<#22509#>(d<#22509#><#22510#>efine<#22510#> <#22511#>(<#22511#><#22512#>test-hours<#22512#><#64489#><#22513#><#22513#><#22514#>-;SPMgt;<#22514#><#22515#><#22515#><#64489#><#22516#>wages<#22516#> <#22517#>a-list<#22517#> <#22518#>another-list<#22518#> <#22519#>expected-result)<#22519#> 
  <#22520#>(c<#22520#><#22521#>ond<#22521#> 
    <#22522#>[<#22522#><#22523#>(list=?<#22523#> <#22524#>(<#22524#><#22525#>hours<#22525#><#64490#><#22526#><#22526#><#22527#>-;SPMgt;<#22527#><#22528#><#22528#><#64490#><#22529#>wages<#22529#> <#22530#>a-list<#22530#> <#22531#>another-list)<#22531#> <#22532#>expected-result)<#22532#> 
     <#22533#>true]<#22533#> 
    <#22534#>[<#22534#><#22535#>else<#22535#> 
     <#22536#>(list<#22536#> <#22537#>``bad<#22537#> <#22538#>test<#22538#> <#22539#>result:''<#22539#> <#22540#>a-list<#22540#> <#22541#>another-list<#22541#> <#22542#>expected-result)]<#22542#><#22543#>))<#22543#> 
<#22547#>Figure: A test function<#22547#>
Indeed, we can go even further. We can write a test function like the one in figure~#figtestfunction#22549>. The class of <#64491#><#22550#>test-result<#22550#><#64491#>s consists of the value <#64492#><#22551#>true<#22551#><#64492#> and lists of four items: the string <#64493#><#22552#>``bad<#22552#>\ <#22553#>test<#22553#>\ <#22554#>result:''<#22554#><#64493#> followed by three lists. Using this new auxiliary function, we can test <#71163#><#22555#>hours<#22555#><#64494#><#22556#><#22556#><#22557#>-;SPMgt;<#22557#><#22558#><#22558#><#64494#><#22559#>wages<#22559#><#71163#> as follows:
<#22564#>(<#22564#><#22565#>test-hours<#22565#><#64495#><#22566#><#22566#><#22567#>-;SPMgt;<#22567#><#22568#><#22568#><#64495#><#22569#>wages<#22569#> 
                        <#22570#>(cons<#22570#> <#22571#>5.65<#22571#> <#22572#>(cons<#22572#> <#22573#>8.75<#22573#> <#22574#>empty))<#22574#> 
                        <#22575#>(cons<#22575#> <#22576#>40<#22576#> <#22577#>(cons<#22577#> <#22578#>30<#22578#> <#22579#>empty))<#22579#> 
                        <#22580#>(cons<#22580#> <#22581#>226.0<#22581#> <#22582#>(cons<#22582#> <#22583#>262.5<#22583#> <#22584#>empty)))<#22584#> 
If something goes wrong with the test cases, the four-item list will stand out and specify precisely which test case failed. The designers of Scheme anticipated the need of a general equality procedure and provide
<#71164#>;; <#64496#><#22592#>equal?<#22592#> <#22593#>:<#22593#> <#22594#>any-value<#22594#> <#22595#>any-value<#22595#> <#22596#><#22596#><#22597#>-;SPMgt;<#22597#><#22598#><#22598#> <#22599#>boolean<#22599#><#64496#><#71164#>
<#22600#>;; to determine whether two values are structurally equivalent <#22600#> 
<#22601#>;; and contain the same atomic values in analogous positions <#22601#> 
When <#64497#><#22605#>equal?<#22605#><#64497#> is applied to two lists, it compares them in the same manner as <#64498#><#22606#>list=?<#22606#><#64498#>; when it encounters a pair of structures, it compares their corresponding fields, if they are the same kind of structures; and when it consumes a pair of atomic values, it compares them with <#64499#><#22607#>=<#22607#><#64499#>, <#64500#><#22608#>symbol=?<#22608#><#64500#>, or <#64501#><#22609#>boolean=?<#22609#><#64501#>, whatever is appropriate.

<#22610#>Unordered Lists<#22610#>:\ On some occasions, we use lists even though the ordering of the items doesn't play a role. For those cases, it is important to have functions such as <#64502#><#22611#>contains-same-numbers<#22611#><#64502#> (see exercise~#exlist5#22612>) if we wish to determine whether the result of some function application contains the proper items.~<#64503#><#64503#>
<#22617#>Exercise 17.8.10<#22617#> Define a test function for <#64504#><#22619#>replace-eol-with<#22619#><#64504#> from section~#sectwoinputscase1#22620> using <#64505#><#22621#>equal?<#22621#><#64505#> and formulate the examples as test cases using this function.~ external Solution<#64506#><#64506#> <#22627#>Exercise 17.8.11<#22627#> Define the function <#64507#><#22629#>test-list-pick<#22629#><#64507#>, which manages test cases for the <#64508#><#22630#>list-pick<#22630#><#64508#> function from section~#sectwoinputscase1#22631>. Formulate the examples from the section as test cases using <#64509#><#22632#>test-list-pick<#22632#><#64509#>.~ external Solution<#64510#><#64510#> <#22638#>Exercise 17.8.12<#22638#> Define <#64511#><#22640#>test-interpret<#22640#><#64511#>, which tests <#64512#><#22641#>interpret-with-defs<#22641#><#64512#> from exercise~#exschemeevaldef#22642>, using <#64513#><#22643#>equal?<#22643#><#64513#>. Re-formulate the test cases using this function.~ external Solution<#64514#><#64514#>