<#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>
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>
<#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.
<#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#>.~
An <#64436#><#22177#>atom<#22177#><#64436#> is eitherDevelop the function <#64437#><#22181#>list-equal?<#22181#><#64437#>, which consumes two lists of atoms and determines whether they are equal.~
- a number
- a boolean
- a symbol
<#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 eitherThe 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:
- <#64445#><#22217#>empty<#22217#><#64445#>;
- <#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- <#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.
<#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.
A <#64470#><#22390#>Slist<#22390#><#64470#> is eitherDevelop 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.~
- <#64471#><#22392#>empty<#22392#><#64471#>
- <#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
- a number
- a boolean
- a symbol
- a <#64478#><#22403#>Slist<#22403#><#64478#>
<#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#>
<#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>
<#22617#>Exercise 17.8.10<#22617#>
Solution<#64506#><#64506#>
<#22627#>Exercise 17.8.11<#22627#>
Solution<#64510#><#64510#>
<#22638#>Exercise 17.8.12<#22638#>
Solution<#64514#><#64514#>