In section~#seclistproduce#19696>, we developed the function
<#71129#><#19697#>hours<#19697#><#64099#><#19698#><#19698#><#19699#>-;SPMgt;<#19699#><#19700#><#19700#><#64099#><#19701#>wages<#19701#><#71129#> for the computation of weekly wages. It consumed a
list of numbers---hours worked per week---and produced a list of weekly
wages. We had based the function on the simplifying assumption that all
employees received the same pay rate. Even a small company, however,
employs people at different rate levels. Typically, the company's
accountant also maintains two collections of information: a permanent one
that, among other things, includes an employee's personal pay-rate, and a
temporary one that records how much time an employee has worked during the
past week.
The revised problem statement means that the function should consume <#19702#>two<#19702#> lists. To simplify the problem, let us assume that the lists are
just lists of numbers, pay rates and weekly hours. Then here is the problem
statement:
<#72223#>;; <#71130#><#19707#>hours<#19707#><#64100#><#19708#><#19708#><#19709#>-;SPMgt;<#19709#><#19710#><#19710#><#64100#><#19711#>wages<#19711#> <#19712#>:<#19712#> <#19713#>list-of-numbers<#19713#> <#19714#>list-of-numbers<#19714#> <#19715#><#19715#><#19716#>-;SPMgt;<#19716#><#19717#><#19717#> <#19718#>list-of-numbers<#19718#><#71130#><#72223#>
<#19719#>;; to construct a new list by multiplying the corresponding items on<#19719#>
<#71131#>;; <#64101#><#19720#>alon1<#19720#><#64101#> and <#64102#><#19721#>alon2<#19721#><#64102#><#71131#>
<#64103#>;; <#19722#>ASSUMPTION<#19722#>: the two lists are of equal length <#64103#>
<#19723#>(define<#19723#> <#19724#>(<#19724#><#19725#>hours<#19725#><#64104#><#19726#><#19726#><#19727#>-;SPMgt;<#19727#><#19728#><#19728#><#64104#><#19729#>wages<#19729#> <#19730#>alon1<#19730#> <#19731#>alon2)<#19731#> <#19732#>...)<#19732#>
We can think of <#64105#><#19736#>alon1<#19736#><#64105#> as the list of pay-rates and of
<#64106#><#19737#>alon2<#19737#><#64106#> as the list of hours worked per week. To get the list of
weekly wages, we must multiply the corresponding numbers in the two input
lists.
Let's look at some examples:
<#19742#>(<#19742#><#19743#>hours<#19743#><#64107#><#19744#><#19744#><#19745#>-;SPMgt;<#19745#><#19746#><#19746#><#64107#><#19747#>wages<#19747#> <#19748#>empty<#19748#> <#19749#>empty)<#19749#>
<#19750#>=<#19750#> <#19751#>empty<#19751#>
<#19759#>(<#19759#><#19760#>hours<#19760#><#64108#><#19761#><#19761#><#19762#>-;SPMgt;<#19762#><#19763#><#19763#><#64108#><#19764#>wages<#19764#> <#19765#>(cons<#19765#> <#19766#>5.65<#19766#> <#19767#>empty)<#19767#>
<#19768#>(cons<#19768#> <#19769#>40<#19769#> <#19770#>empty))<#19770#>
<#19771#>=<#19771#> <#19772#>(cons<#19772#> <#19773#>226.0<#19773#> <#19774#>empty)<#19774#>
<#19782#>(<#19782#><#19783#>hours<#19783#><#64109#><#19784#><#19784#><#19785#>-;SPMgt;<#19785#><#19786#><#19786#><#64109#><#19787#>wages<#19787#> <#19788#>(cons<#19788#> <#19789#>5.65<#19789#> <#19790#>(cons<#19790#> <#19791#>8.75<#19791#> <#19792#>empty))<#19792#>
<#19793#>(cons<#19793#> <#19794#>40<#19794#> <#19795#>(cons<#19795#> <#19796#>30<#19796#> <#19797#>empty)))<#19797#>
<#19798#>=<#19798#> <#19799#>(cons<#19799#> <#19800#>226.0<#19800#> <#19801#>(cons<#19801#> <#19802#>262.5<#19802#> <#19803#>empty))<#19803#>
For all three examples the function is applied to two lists of equal
length. As stated in the addendum to the purpose statement, the function
assumes this and, indeed, using the function makes no sense if the condition
is violated.
The condition on the inputs can also be exploited for the development of
the template. Put more concretely, the condition says that <#64110#><#19807#>(empty?<#19807#><#19808#> <#19808#><#19809#>alon1)<#19809#><#64110#> is true if, and only if, <#64111#><#19810#>(empty?<#19810#>\ <#19811#>alon2)<#19811#><#64111#> is true; and
furthermore, <#64112#><#19812#>(cons?<#19812#>\ <#19813#>alon1)<#19813#><#64112#> is true if, and only if, <#64113#><#19814#>(cons?<#19814#><#19815#> <#19815#><#19816#>alon2)<#19816#><#64113#> is true. In other words, the condition simplifies the design of the
template's <#64114#><#19817#>cond<#19817#><#64114#>-structure, because it says the template is similar
to that of a plain list-processing function:
<#19822#>(d<#19822#><#19823#>efine<#19823#> <#19824#>(<#19824#><#19825#>hours<#19825#><#64115#><#19826#><#19826#><#19827#>-;SPMgt;<#19827#><#19828#><#19828#><#64115#><#19829#>wages<#19829#> <#19830#>alon1<#19830#> <#19831#>alon2)<#19831#>
<#19832#>(c<#19832#><#19833#>ond<#19833#>
<#19834#>((empty?<#19834#> <#19835#>alon1)<#19835#> <#19836#>...)<#19836#>
<#19837#>(else<#19837#> <#19838#>...<#19838#> <#19839#>)))<#19839#>
In the first <#64116#><#19843#>cond<#19843#><#64116#>-clause, both <#64117#><#19844#>alon1<#19844#><#64117#> and <#64118#><#19845#>alon2<#19845#><#64118#>
are <#64119#><#19846#>empty<#19846#><#64119#>. Hence, no selector expressions are needed. In the
second clause, both <#64120#><#19847#>alon1<#19847#><#64120#> and <#64121#><#19848#>alon2<#19848#><#64121#> are
<#64122#><#19849#>cons<#19849#><#64122#>tructed lists, which means we need four selector expressions:
<#19854#>(d<#19854#><#19855#>efine<#19855#> <#19856#>(<#19856#><#19857#>hours<#19857#><#64123#><#19858#><#19858#><#19859#>-;SPMgt;<#19859#><#19860#><#19860#><#64123#><#19861#>wages<#19861#> <#19862#>alon1<#19862#> <#19863#>alon2)<#19863#>
<#19864#>(c<#19864#><#19865#>ond<#19865#>
<#19866#>((empty?<#19866#> <#19867#>alon1)<#19867#> <#19868#>...)<#19868#>
<#19869#>(e<#19869#><#19870#>lse<#19870#>
<#19871#>...<#19871#> <#19872#>(first<#19872#> <#19873#>alon1)<#19873#> <#19874#>...<#19874#> <#19875#>(first<#19875#> <#19876#>alon2)<#19876#> <#19877#>...<#19877#>
<#19878#>...<#19878#> <#19879#>(rest<#19879#> <#19880#>alon1)<#19880#> <#19881#>...<#19881#> <#19882#>(rest<#19882#> <#19883#>alon2)<#19883#> <#19884#>...<#19884#> <#19885#>)))<#19885#>
Finally, because the last two are lists of equal length, they make up a
natural candidate for the natural recursion of <#71132#><#19889#>hours<#19889#><#64124#><#19890#><#19890#><#19891#>-;SPMgt;<#19891#><#19892#><#19892#><#64124#><#19893#>wages<#19893#><#71132#>:
<#19898#>(d<#19898#><#19899#>efine<#19899#> <#19900#>(<#19900#><#19901#>hours<#19901#><#64125#><#19902#><#19902#><#19903#>-;SPMgt;<#19903#><#19904#><#19904#><#64125#><#19905#>wages<#19905#> <#19906#>alon1<#19906#> <#19907#>alon2)<#19907#>
<#19908#>(c<#19908#><#19909#>ond<#19909#>
<#19910#>((empty?<#19910#> <#19911#>alon1)<#19911#> <#19912#>...)<#19912#>
<#19913#>(e<#19913#><#19914#>lse<#19914#>
<#19915#>...<#19915#> <#19916#>(first<#19916#> <#19917#>alon1)<#19917#> <#19918#>...<#19918#> <#19919#>(first<#19919#> <#19920#>alon2)<#19920#> <#19921#>...<#19921#>
<#19922#>...<#19922#> <#19923#>(<#19923#><#19924#>hours<#19924#><#64126#><#19925#><#19925#><#19926#>-;SPMgt;<#19926#><#19927#><#19927#><#64126#><#19928#>wages<#19928#> <#19929#>(rest<#19929#> <#19930#>alon1)<#19930#> <#19931#>(rest<#19931#> <#19932#>alon2))<#19932#> <#19933#>...<#19933#> <#19934#>)))<#19934#>
The only unusual aspect of this template is that the recursive application
consists of two expressions, both selector expressions for the two
arguments. But, as we have seen, the idea is easily explicable due to the
assumption that <#64127#><#19938#>alon1<#19938#><#64127#> and <#64128#><#19939#>alon2<#19939#><#64128#> are of equal length.
<#72224#>;; <#71133#><#19944#>hours<#19944#><#64129#><#19945#><#19945#><#19946#>-;SPMgt;<#19946#><#19947#><#19947#><#64129#><#19948#>wages<#19948#> <#19949#>:<#19949#> <#19950#>list-of-numbers<#19950#> <#19951#>list-of-numbers<#19951#> <#19952#><#19952#><#19953#>-;SPMgt;<#19953#><#19954#><#19954#> <#19955#>list-of-numbers<#19955#><#71133#><#72224#>
<#19956#>;; to construct a new list by multiplying the corresponding items on<#19956#>
<#64130#>;; <#19957#>ASSUMPTION<#19957#>: the two lists are of equal length <#64130#>
<#71134#>;; <#64131#><#19958#>alon1<#19958#><#64131#> and <#64132#><#19959#>alon2<#19959#><#64132#><#71134#>
<#19960#>(d<#19960#><#19961#>efine<#19961#> <#19962#>(<#19962#><#19963#>hours<#19963#><#64133#><#19964#><#19964#><#19965#>-;SPMgt;<#19965#><#19966#><#19966#><#64133#><#19967#>wages<#19967#> <#19968#>alon1<#19968#> <#19969#>alon2)<#19969#>
<#19970#>(c<#19970#><#19971#>ond<#19971#>
<#19972#>((empty?<#19972#> <#19973#>alon1)<#19973#> <#19974#>empty)<#19974#>
<#19975#>(else<#19975#> <#19976#>(cons<#19976#> <#19977#>(weekly-wage<#19977#> <#19978#>(first<#19978#> <#19979#>alon1)<#19979#> <#19980#>(first<#19980#> <#19981#>alon2))<#19981#>
<#19982#>(<#19982#><#19983#>hours<#19983#><#64134#><#19984#><#19984#><#19985#>-;SPMgt;<#19985#><#19986#><#19986#><#64134#><#19987#>wages<#19987#> <#19988#>(rest<#19988#> <#19989#>alon1)<#19989#> <#19990#>(rest<#19990#> <#19991#>alon2))))))<#19991#>
<#71135#>;; <#64135#><#19992#>weekly-wage<#19992#> <#19993#>:<#19993#> <#19994#>number<#19994#> <#19995#>number<#19995#> <#19996#><#19996#><#19997#>-;SPMgt;<#19997#><#19998#><#19998#> <#19999#>number<#19999#><#64135#><#71135#>
<#71136#>;; to compute the weekly wage from <#64136#><#20000#>pay-rate<#20000#><#64136#> and <#64137#><#20001#>hours-worked<#20001#><#64137#><#71136#>
<#20002#>(d<#20002#><#20003#>efine<#20003#> <#20004#>(weekly-wage<#20004#> <#20005#>pay-rate<#20005#> <#20006#>hours-worked)<#20006#>
<#20007#>(*<#20007#> <#20008#>pay-rate<#20008#> <#20009#>hours-worked))<#20009#>
<#64138#>Figure: The complete definition of <#20013#>hours<#20013#>#tex2html_wrap_inline73080#<#20014#>wage<#20014#><#64138#>
To define the function from here, we follow the design recipe. The first
example implies that the answer for the first <#64139#><#20016#>cond<#20016#><#64139#>-clause is
<#64140#><#20017#>empty<#20017#><#64140#>. In the second one, we have three values available:
- <#64141#><#20019#>(first<#20019#>\ <#20020#>alon1)<#20020#><#64141#> evaluates to the first item on the list of
pay-rates;
- <#64142#><#20021#>(first<#20021#>\ <#20022#>alon2)<#20022#><#64142#> evaluates to the first item on the list of
hours worked; and
- <#71137#><#20023#>(<#20023#><#20024#>hours<#20024#><#64143#><#20025#><#20025#><#20026#>-;SPMgt;<#20026#><#20027#><#20027#><#64143#><#20028#>wages<#20028#>\ <#20029#>(rest<#20029#>\ <#20030#>alon1)<#20030#>\ <#20031#>(rest<#20031#>\ <#20032#>alon2))<#20032#><#71137#> computes the list
of weekly wages for the remainders of <#64144#><#20033#>alon1<#20033#><#64144#> and <#64145#><#20034#>alon2<#20034#><#64145#>.
We merely need to combine these values to get the final answer. More
specifically, given the purpose statement, we must compute the weekly wage
for the first employee and <#64146#><#20036#>cons<#20036#><#64146#>truct a list from that wage and the
rest of the wages. This suggests the following answer for the second
<#64147#><#20037#>cond<#20037#><#64147#>-clause:
<#20042#>(cons<#20042#> <#20043#>(weekly-wage<#20043#> <#20044#>(first<#20044#> <#20045#>alon1)<#20045#> <#20046#>(first<#20046#> <#20047#>alon2))<#20047#>
<#20048#>(<#20048#><#20049#>hours<#20049#><#64148#><#20050#><#20050#><#20051#>-;SPMgt;<#20051#><#20052#><#20052#><#64148#><#20053#>wages<#20053#> <#20054#>(rest<#20054#> <#20055#>alon1)<#20055#> <#20056#>(rest<#20056#> <#20057#>alon2)))<#20057#>
The auxiliary function <#64149#><#20061#>weekly-wage<#20061#><#64149#> consumes the two first items and
computes the weekly wage. Figure~#fighourswage#20062> contains the complete
definitions.
<#20065#>Exercise 17.2.1<#20065#>
In the real world, <#71138#><#20067#>hours<#20067#><#64150#><#20068#><#20068#><#20069#>-;SPMgt;<#20069#><#20070#><#20070#><#64150#><#20071#>wages<#20071#><#71138#> consumes lists of employee
structures and lists of work structures. An employee structure contains an
employee's name, social security number, and pay rate. A work structure
contains an employee's name and the number of hours worked in a week. The
result is a list of structures that contain the name of the employee and
the weekly wage.
Modify the function in figure~#fighourswage#20072> so that it works on these
classes of data. Provide the necessary structure definitions and data
definitions. Use the design recipe to guide the modification
process.~ Solution<#64151#><#64151#>
<#20078#>Exercise 17.2.2<#20078#>
Develop the function <#64152#><#20080#>zip<#20080#><#64152#>, which combines a list of names and a list
phone numbers into a list of phone records. Assuming the following structure
definition:
<#20085#>(define-struct<#20085#> <#20086#>phone-record<#20086#> <#20087#>(name<#20087#> <#20088#>number))<#20088#> <#20089#>,<#20089#>
a phone record is constructed with <#64153#><#20093#>(make-phone-record<#20093#>\ <#20094#>s<#20094#>\ <#20095#>n)<#20095#><#64153#> where
<#64154#><#20096#>s<#20096#><#64154#> is a symbol and <#64155#><#20097#>n<#20097#><#64155#> is a number. Assume the lists are of
equal length. Simplify the definition, if possible. Solution<#64156#><#64156#>