Functions that Produce Lists

Recall the function <#62304#><#10905#>wage<#10905#><#62304#> from section~#secbasicswordprobs#10906>:
<#70970#>;; <#62305#><#10911#>wage<#10911#> <#10912#>:<#10912#> <#10913#>number<#10913#> <#10914#><#10914#><#10915#>-;SPMgt;<#10915#><#10916#><#10916#> <#10917#>number<#10917#><#62305#><#70970#>
<#10918#>;; to compute the total wage (at $12 per hour)<#10918#> 
<#70971#>;; of someone who worked for <#62306#><#10919#>h<#10919#><#62306#> hours<#70971#> 
<#10920#>(d<#10920#><#10921#>efine<#10921#> <#10922#>(wage<#10922#> <#10923#>h)<#10923#> 
  <#10924#>(*<#10924#> <#10925#>12<#10925#> <#10926#>h))<#10926#> 
The <#62307#><#10930#>wage<#10930#><#62307#> function consumes the number of hours some employee worked and produces the weekly wage payment. For simplicity, we assume that all employees earn the same hourly rate, namely, $12. A company, however, isn't interested in a function like <#62308#><#10931#>wage<#10931#><#62308#>, which computes the wage of a single employee. Instead, it wants a function that computes the wages for all of its employees, especially if there are a lot of them. Call this new function <#70972#><#10932#>hours<#10932#><#62309#><#10933#><#10933#><#10934#>-;SPMgt;<#10934#><#10935#><#10935#><#62309#><#10936#>wages<#10936#><#70972#>. It consumes a list that represents how many hours the employees of the company worked and must produce a list of the weekly wages they earned. We can represent both the input and the output as Scheme lists of numbers. Since we already have a data definition for the inputs and outputs, we can immediately start our function development:
<#72198#>;; <#70973#><#10941#>hours<#10941#><#62310#><#10942#><#10942#><#10943#>-;SPMgt;<#10943#><#10944#><#10944#><#62310#><#10945#>wages<#10945#> <#10946#>:<#10946#> <#10947#>list-of-numbers<#10947#> <#10948#><#10948#><#10949#>-;SPMgt;<#10949#><#10950#><#10950#> <#10951#>list-of-numbers<#10951#><#70973#><#72198#>
<#70974#>;; to create a list of weekly wages from a list of weekly hours (<#62311#><#10952#>alon<#10952#><#62311#>)<#70974#> 
<#10953#>(define<#10953#> <#10954#>(<#10954#><#10955#>hours<#10955#><#62312#><#10956#><#10956#><#10957#>-;SPMgt;<#10957#><#10958#><#10958#><#62312#><#10959#>wages<#10959#> <#10960#>alon)<#10960#> <#10961#>...)<#10961#> 
Next we need some examples of inputs and the corresponding outputs:
<#10969#>empty<#10969#>
<#10970#>(cons<#10970#> <#10971#>28<#10971#> <#10972#>empty)<#10972#> 
<#10973#>(cons<#10973#> <#10974#>40<#10974#> <#10975#>(cons<#10975#> <#10976#>28<#10976#> <#10977#>empty))<#10977#> 
~~
<#10983#>empty<#10983#>
<#10984#>(cons<#10984#> <#10985#>336<#10985#> <#10986#>empty)<#10986#> 
<#10987#>(cons<#10987#> <#10988#>480<#10988#> <#10989#>(cons<#10989#> <#10990#>336<#10990#> <#10991#>empty))<#10991#> 
The outputs are obtained by calculating the wage for each item on the list to the left. Given that <#70975#><#10995#>hours<#10995#><#62313#><#10996#><#10996#><#10997#>-;SPMgt;<#10997#><#10998#><#10998#><#62313#><#10999#>wages<#10999#><#70975#> consumes the same class of data as, say, the function <#62314#><#11000#>sum<#11000#><#62314#>, and given that the shape of a function template depends only on the shape of the data definition, we can reuse the <#62315#><#11001#>list-of-numbers<#11001#><#62315#> template:
<#11006#>(d<#11006#><#11007#>efine<#11007#> <#11008#>(<#11008#><#11009#>hours<#11009#><#62316#><#11010#><#11010#><#11011#>-;SPMgt;<#11011#><#11012#><#11012#><#62316#><#11013#>wages<#11013#> <#11014#>alon)<#11014#>
  <#11015#>(c<#11015#><#11016#>ond<#11016#> 
    <#11017#>[<#11017#><#11018#>(empty?<#11018#> <#11019#>alon)<#11019#> <#11020#>...]<#11020#> 
    <#11021#>[<#11021#><#11022#>else<#11022#> <#11023#>...<#11023#> <#11024#>(first<#11024#> <#11025#>alon)<#11025#> <#11026#>...<#11026#> <#11027#>(<#11027#><#11028#>hours<#11028#><#62317#><#11029#><#11029#><#11030#>-;SPMgt;<#11030#><#11031#><#11031#><#62317#><#11032#>wages<#11032#> <#11033#>(rest<#11033#> <#11034#>alon))<#11034#> <#11035#>...]<#11035#><#11036#>))<#11036#> 
Starting with this template, we can turn to the most creative step of function development: the definition of the function body. Following our recipe, we consider each <#62318#><#11040#>cond<#11040#><#62318#>-line in isolation, starting with the simpler case. First, assume <#62319#><#11041#>(empty?<#11041#>\ <#11042#>alon)<#11042#><#62319#> is true, which means that the input is <#62320#><#11043#>empty<#11043#><#62320#>. The answer in this case is <#62321#><#11044#>empty<#11044#><#62321#>:
<#11049#>(d<#11049#><#11050#>efine<#11050#> <#11051#>(<#11051#><#11052#>hours<#11052#><#62322#><#11053#><#11053#><#11054#>-;SPMgt;<#11054#><#11055#><#11055#><#62322#><#11056#>wages<#11056#> <#11057#>alon)<#11057#>
  <#11058#>(c<#11058#><#11059#>ond<#11059#> 
    <#11060#>[<#11060#><#11061#>(empty?<#11061#> <#11062#>alon)<#11062#> <#11063#>empty]<#11063#> 
    <#11064#>[<#11064#><#11065#>else<#11065#> <#11066#>...<#11066#> <#11067#>(first<#11067#> <#11068#>alon)<#11068#> <#11069#>...<#11069#> <#11070#>(<#11070#><#11071#>hours<#11071#><#62323#><#11072#><#11072#><#11073#>-;SPMgt;<#11073#><#11074#><#11074#><#62323#><#11075#>wages<#11075#> <#11076#>(rest<#11076#> <#11077#>alon))<#11077#> <#11078#>...]<#11078#><#11079#>))<#11079#> 
Second, assume that <#62324#><#11083#>alon<#11083#><#62324#> was <#62325#><#11084#>cons<#11084#><#62325#>tructed from a number and a list of numbers. The expressions in the second line remind us of this assumption, and the recipe tells us that we should state explicitly what they compute:
  1. <#62326#><#11086#>(first<#11086#>\ <#11087#>alon)<#11087#><#62326#> yields the first number on <#62327#><#11088#>alon<#11088#><#62327#>, which is the first number of hours worked; and
  2. <#70976#><#11089#>(<#11089#><#11090#>hours<#11090#><#62328#><#11091#><#11091#><#11092#>-;SPMgt;<#11092#><#11093#><#11093#><#62328#><#11094#>wages<#11094#>\ <#11095#>(rest<#11095#>\ <#11096#>alon))<#11096#><#70976#> reminds us that <#62329#><#11097#>(rest<#11097#><#11098#> <#11098#><#11099#>alon)<#11099#><#62329#> is a list and can be processed by the very function we are defining. According to the purpose statement, the expression computes the list of wages for the rest of the list of hours, and we may assume this relationship in our construction---even though the function is not yet completely defined.
From here it is a short step to the complete function definition. Since we already have the list of wages for all but the first item of <#62330#><#11101#>alon<#11101#><#62330#>, the function must do two things to produce an output for the <#11102#>entire<#11102#> list of hours:
  1. Compute the weekly wage for the first number of hours.
  2. Construct a list that represents all weekly wages for <#62331#><#11104#>alon<#11104#><#62331#>, using the first weekly wage and the list of weekly wages for <#62332#><#11105#>(rest<#11105#><#11106#> <#11106#><#11107#>alon)<#11107#><#62332#>.
For the first part, we reuse <#62333#><#11109#>wage<#11109#><#62333#>. For the second, we <#62334#><#11110#>cons<#11110#><#62334#> the two pieces of information together into one list:
<#11115#>(cons<#11115#> <#11116#>(wage<#11116#> <#11117#>(first<#11117#> <#11118#>alon))<#11118#> <#11119#>(<#11119#><#11120#>hours<#11120#><#62335#><#11121#><#11121#><#11122#>-;SPMgt;<#11122#><#11123#><#11123#><#62335#><#11124#>wages<#11124#> <#11125#>(rest<#11125#> <#11126#>alon)))<#11126#>
And with that, we have a complete function, as shown in figure~#fighoursSPMgtwages#11130>; to finish the development, we must still test the function.
<#72199#>;; <#70977#><#11135#>hours<#11135#><#62336#><#11136#><#11136#><#11137#>-;SPMgt;<#11137#><#11138#><#11138#><#62336#><#11139#>wages<#11139#> <#11140#>:<#11140#> <#11141#>list-of-numbers<#11141#> <#11142#><#11142#><#11143#>-;SPMgt;<#11143#><#11144#><#11144#> <#11145#>list-of-numbers<#11145#><#70977#><#72199#>
<#70978#>;; to create a list of weekly wages from a list of weekly hours (<#62337#><#11146#>alon<#11146#><#62337#>)<#70978#> 
<#11147#>(d<#11147#><#11148#>efine<#11148#> <#11149#>(<#11149#><#11150#>hours<#11150#><#62338#><#11151#><#11151#><#11152#>-;SPMgt;<#11152#><#11153#><#11153#><#62338#><#11154#>wages<#11154#> <#11155#>alon)<#11155#> 
  <#11156#>(c<#11156#><#11157#>ond<#11157#> 
    <#11158#>[<#11158#><#11159#>(empty?<#11159#> <#11160#>alon)<#11160#> <#11161#>empty]<#11161#> 
    <#11162#>[<#11162#><#11163#>else<#11163#> <#11164#>(cons<#11164#> <#11165#>(wage<#11165#> <#11166#>(first<#11166#> <#11167#>alon))<#11167#> <#11168#>(<#11168#><#11169#>hours<#11169#><#62339#><#11170#><#11170#><#11171#>-;SPMgt;<#11171#><#11172#><#11172#><#62339#><#11173#>wages<#11173#> <#11174#>(rest<#11174#> <#11175#>alon)))]<#11175#><#11176#>))<#11176#> 
<#70979#>;; <#62340#><#11177#>wage<#11177#> <#11178#>:<#11178#> <#11179#>number<#11179#> <#11180#><#11180#><#11181#>-;SPMgt;<#11181#><#11182#><#11182#> <#11183#>number<#11183#><#62340#><#70979#> 
<#11184#>;; to compute the total wage (at $12 per hour)<#11184#> 
<#70980#>;; of someone who worked for <#62341#><#11185#>h<#11185#><#62341#> hours<#70980#> 
<#11186#>(d<#11186#><#11187#>efine<#11187#> <#11188#>(wage<#11188#> <#11189#>h)<#11189#> 
  <#11190#>(*<#11190#> <#11191#>12<#11191#> <#11192#>h))<#11192#> 
<#11196#>Figure: Computing weekly wages<#11196#>

<#11200#>Exercise 10.1.1<#11200#> How do we have to change the function in figure~#fighoursSPMgtwages#11202> if we want to give everyone a raise to $14?~ external Solution<#62342#><#62342#> <#11208#>Exercise 10.1.2<#11208#> No employee could possibly work more than 100 hours per week. To protect the company against fraud, the function should check that no item of the input list of <#70981#><#11210#>hours<#11210#><#62343#><#11211#><#11211#><#11212#>-;SPMgt;<#11212#><#11213#><#11213#><#62343#><#11214#>wages<#11214#><#70981#> exceeds 100. If one of them does, the function should immediately signal the error <#62344#><#11215#>``too<#11215#>\ <#11216#>many<#11216#>\ <#11217#>hours''<#11217#><#62344#>. How do we have to change the function in figure~#fighoursSPMgtwages#11218> if we want to perform this basic reality check?~ external Solution<#62345#><#62345#> <#11224#>Exercise 10.1.3<#11224#> external ~<#11227#>For this and some of the following exercises, ask students to show the products of the various steps in the design recipe. Diagnose students weaknesses! Up to now, design recipes were easy to apply; but unless students have practiced them consistently, they will fail now.<#11227#> Develop <#62346#><#11228#>convertFC<#11228#><#62346#>. The function converts a list of Fahrenheit measurements to a list of Celsius measurements. external Solution<#62347#><#62347#> <#11234#>Exercise 10.1.4<#11234#> Develop the function <#62348#><#11237#>convertDM<#11237#><#62348#>, which converts a list of US Dollar amounts into a list of Deutsche Mark amounts. Assume the exchange rate is 1.82 marks for each dollar. Generalize <#62349#><#11238#>convertDM<#11238#><#62349#> to the function <#62350#><#11239#>convertDM1<#11239#><#62350#>, which consumes an exchange rate and a list of dollar amounts and converts the latter into a list of Deutsche Mark accounts. external Solution<#62351#><#62351#> <#11245#>Exercise 10.1.5<#11245#> Develop the function <#62352#><#11247#>eliminate-exp<#11247#><#62352#> to eliminate expensive toys. The function consumes a number, called <#62353#><#11248#>ua<#11248#><#62353#>, and a list of toy prices, called <#62354#><#11249#>lotp<#11249#><#62354#>, and produces a list of all those prices in <#62355#><#11250#>lotp<#11250#><#62355#> that are below <#62356#><#11251#>ua<#11251#><#62356#>. For example,
  <#11256#>(eliminate-exp<#11256#> <#11257#>1.0<#11257#> <#11258#>(cons<#11258#> <#11259#>2.95<#11259#> <#11260#>(cons<#11260#> <#11261#>.95<#11261#> <#11262#>(cons<#11262#> <#11263#>1.0<#11263#> <#11264#>(cons<#11264#> <#11265#>5<#11265#> <#11266#>empty)))))<#11266#>
<#11267#>=<#11267#> <#11268#>(cons<#11268#> <#11269#>.95<#11269#> <#11270#>(cons<#11270#> <#11271#>1.0<#11271#> <#11272#>empty))<#11272#> 
external Solution<#62357#><#62357#> <#11281#>Exercise 10.1.6<#11281#> Develop the function <#62358#><#11283#>name-robot<#11283#><#62358#>, which consumes a list of toy descriptions (names) and produces an equivalent list of more accurate descriptions. Specifically, it replaces all occurrences of <#62359#><#11284#>'<#11284#><#11285#>robot<#11285#><#62359#> with <#62360#><#11286#>'<#11286#><#11287#>r2d3<#11287#><#62360#> and otherwise retains the toy descriptions in the same order. Generalize <#62361#><#11288#>name-robot<#11288#><#62361#> to the function <#62362#><#11289#>substitute<#11289#><#62362#>. The new function consumes two symbols, called <#62363#><#11290#>new<#11290#><#62363#> and <#62364#><#11291#>old<#11291#><#62364#>, and a list of symbols. It produces a new list of symbols by substituting all occurrences of <#62365#><#11292#>old<#11292#><#62365#> by <#62366#><#11293#>new<#11293#><#62366#>. For example,
  <#11298#>(substitute<#11298#> <#11299#>'<#11299#><#11300#>Barbie<#11300#> <#11301#>'<#11301#><#11302#>doll<#11302#> <#11303#>(cons<#11303#> <#11304#>'<#11304#><#11305#>robot<#11305#> <#11306#>(cons<#11306#> <#11307#>'<#11307#><#11308#>doll<#11308#> <#11309#>(cons<#11309#> <#11310#>'<#11310#><#11311#>dress<#11311#> <#11312#>empty))))<#11312#>
<#11313#>=<#11313#> <#11314#>(cons<#11314#> <#11315#>'<#11315#><#11316#>robot<#11316#> <#11317#>(cons<#11317#> <#11318#>'<#11318#><#11319#>Barbie<#11319#> <#11320#>(cons<#11320#> <#11321#>'<#11321#><#11322#>dress<#11322#> <#11323#>empty)))<#11323#> 
external Solution<#62367#><#62367#> <#11332#>Exercise 10.1.7<#11332#> Develop the function <#62368#><#11334#>recall<#11334#><#62368#> to eliminate specific toys from a list. The function consumes the name of a toy, called <#62369#><#11335#>ty<#11335#><#62369#>, and a list of names, called <#62370#><#11336#>lon<#11336#><#62370#>, and produces a list of names that contains all components of <#62371#><#11337#>lon<#11337#><#62371#> with the exception of <#62372#><#11338#>ty<#11338#><#62372#>. For example,
  <#11343#>(recall<#11343#> <#11344#>'<#11344#><#11345#>robot<#11345#> <#11346#>(cons<#11346#> <#11347#>'<#11347#><#11348#>robot<#11348#> <#11349#>(cons<#11349#> <#11350#>'<#11350#><#11351#>doll<#11351#> <#11352#>(cons<#11352#> <#11353#>'<#11353#><#11354#>dress<#11354#> <#11355#>empty))))<#11355#>
<#11356#>=<#11356#> <#11357#>(cons<#11357#> <#11358#>'<#11358#><#11359#>doll<#11359#> <#11360#>(cons<#11360#> <#11361#>'<#11361#><#11362#>dress<#11362#> <#11363#>empty))<#11363#> 
external Solution<#62373#><#62373#> <#11372#>Exercise 10.1.8<#11372#> #drnexquad3#11375> Develop <#62375#><#11376#>quadratic-roots<#11376#><#62375#>, which solves quadratic equations: see exercises~#exquad1#11377> and~#exquad2#11378>. The function accepts the coefficients <#62376#><#11379#>a<#11379#><#62376#>, <#62377#><#11380#>b<#11380#><#62377#>, and <#62378#><#11381#>c<#11381#><#62378#>. The computations it performs depend on the input:
  1. if a = 0, its output is <#62379#><#11383#>'<#11383#><#11384#>degenerate<#11384#><#62379#>.
  2. if #tex2html_wrap_inline72988#, the quadratic equation has no solution; <#62380#><#11385#>quadratic-roots<#11385#><#62380#> produces <#62381#><#11386#>'<#11386#><#11387#>none<#11387#><#62381#> in this case.
  3. if #tex2html_wrap_inline72990#, the equation has one solution:

    #displaymath72992#

    the solution is the answer.

  4. if #tex2html_wrap_inline72994#, the equation has two solutions:

    #displaymath72996#

    and

    #displaymath72998#

    the result is a list of two numbers: the first solution followed by the second solution.

Test the function with the examples from exercises~#exquad1#11395> and~#exquad2#11396>. First decide the answer for each example, then determine it with DrScheme.~ external Solution<#62384#><#62384#> <#11402#>Exercise 10.1.9<#11402#> The cash registers at many grocery stores talk to customers. The register's computer receives the number of cents that the customer must pay and then builds a list with the following five items:
  1. the dollar amount;
  2. the symbol <#62385#><#11405#>'<#11405#><#11406#>dollar<#11406#><#62385#> if the dollar amount is <#62386#><#11407#>1<#11407#><#62386#> and <#62387#><#11408#>'<#11408#><#11409#>dollars<#11409#><#62387#> otherwise;
  3. the symbol <#62388#><#11410#>'<#11410#><#11411#>and<#11411#><#62388#>
  4. the cent amount; and
  5. the symbol <#62389#><#11412#>'<#11412#><#11413#>cent<#11413#><#62389#> if the cent amount is 1 and <#62390#><#11414#>'<#11414#><#11415#>cents<#11415#><#62390#> otherwise.
Develop the function <#62391#><#11417#>controller<#11417#><#62391#>, which consumes a number and produces a list according to the above description. For example, if the amount is $1.03, then the cash register evaluates <#62392#><#11418#>(controller<#11418#>\ <#11419#>103)<#11419#><#62392#>:
  <#11424#>(controller<#11424#> <#11425#>103)<#11425#>
<#11426#>=<#11426#> <#11427#>(cons<#11427#> <#11428#>1<#11428#> <#11429#>(cons<#11429#> <#11430#>'<#11430#><#11431#>dollar<#11431#> <#11432#>(cons<#11432#> <#11433#>'<#11433#><#11434#>and<#11434#> <#11435#>(cons<#11435#> <#11436#>3<#11436#> <#11437#>(cons<#11437#> <#11438#>'<#11438#><#11439#>cents<#11439#> <#11440#>empty)))))<#11440#> 
<#11444#>Hint<#11444#>: Scheme provides the arithmetic operations <#62393#><#11445#>quotient<#11445#><#62393#> and <#62394#><#11446#>remainder<#11446#><#62394#>, which produce the quotient and remainder of the expression n/m for integers <#11447#>n<#11447#> and <#11448#>m<#11448#>, respectively. external ~<#11450#>The sound teachpack is available on Unix workstations only.<#11450#> Once the controller returns the correct list for amounts whose dollar and cent amounts are between 0 and 20, test the controller with a computer that can speak. Set the teachpack to <#11451#>sound.ss<#11451#>, which makes two operations available: <#62395#><#11452#>speak-word<#11452#><#62395#> and <#62396#><#11453#>speak-list<#11453#><#62396#>. The first accepts a symbol or a number, the second a list of symbols and numbers. Both pronounce the symbols they consume. Evaluate the following expressions <#62397#><#11454#>(speak-word<#11454#>\ <#11455#>1)<#11455#><#62397#>, <#62398#><#11456#>(speak-list<#11456#>\ <#11457#>(cons<#11457#>\ <#11458#>1<#11458#>\ <#11459#>(cons<#11459#><#11460#> <#11460#><#11461#>'<#11461#><#11462#>dollar<#11462#>\ <#11463#>empty)))<#11463#><#62398#>, and <#62399#><#11464#>(speak-list<#11464#>\ <#11465#>(cons<#11465#>\ <#11466#>'<#11466#><#11467#>beautiful<#11467#>\ <#11468#>(cons<#11468#>\ <#11469#>'<#11469#><#11470#>lady<#11470#><#11471#> <#11471#><#11472#>empty)))<#11472#><#62399#> to understand how the operations operate.

<#11473#>Simple Challenge<#11473#>: The sound teachpack only contains the sounds for the numbers <#62400#><#11474#>0<#11474#><#62400#> through <#62401#><#11475#>20<#11475#><#62401#> and <#62402#><#11476#>30<#11476#><#62402#>, <#62403#><#11477#>40<#11477#><#62403#>, <#62404#><#11478#>50<#11478#><#62404#>, <#62405#><#11479#>60<#11479#><#62405#>, <#62406#><#11480#>70<#11480#><#62406#>, <#62407#><#11481#>80<#11481#><#62407#>, and <#62408#><#11482#>90<#11482#><#62408#>. Because of this restriction, the bonus problem only works on amounts with cents and dollars between <#62409#><#11483#>0<#11483#><#62409#> to <#62410#><#11484#>20<#11484#><#62410#>. Implement a controller that deals with arbitrary amounts between 0 and 99.99. external Solution<#62411#><#62411#>