More on Procssing Simple Lists

Let us now look at another aspect of inventory management: the cost of an inventory. In addition to a list of the available toys, a store owner should also maintain a list of the cost of each item. The cost list permits the owner to determine how much the current inventory is worth or, given the inventory at the beginning of the year and that of the end of the year, how much profit the store makes. A list of costs is most easily represented as a list of numbers:
<#10450#>empty<#10450#>
<#10451#>(cons<#10451#> <#10452#>1.22<#10452#> <#10453#>empty)<#10453#> 
<#10454#>(cons<#10454#> <#10455#>2.59<#10455#> <#10456#>empty)<#10456#> 
<#10457#>(cons<#10457#> <#10458#>1.22<#10458#> <#10459#>(cons<#10459#> <#10460#>2.59<#10460#> <#10461#>empty))<#10461#> 
<#10462#>(cons<#10462#> <#10463#>17.05<#10463#> <#10464#>(cons<#10464#> <#10465#>1.22<#10465#> <#10466#>(cons<#10466#> <#10467#>2.59<#10467#> <#10468#>empty)))<#10468#> 
Again, for a real store, we cannot place an arbitrary limit on the size of such a list, and functions that process such cost lists must be prepared to consume lists of arbitrary size. Suppose the toy store needs a function that computes the value of an inventory from the cost of the individual toys. We call this function <#62231#><#10472#>sum<#10472#><#62231#>. Before we can define <#62232#><#10473#>sum<#10473#><#62232#>, we must figure out how to describe all possible lists of numbers that the function may consume. In short, we need a data definition that precisely defines what an arbitrarily large list of numbers is. We can obtain this definition by replacing ``symbol'' with ``number'' in the definition of lists of symbols:
A <#62233#><#10475#>list of numbers<#10475#><#62233#> (<#62234#><#10476#>list-of-numbers<#10476#><#62234#>) is either
  1. the empty list, <#62235#><#10478#>empty<#10478#><#62235#>, or
  2. <#62236#><#10479#>(cons<#10479#>\ <#10480#>n<#10480#>\ <#10481#>lon)<#10481#><#62236#> where <#62237#><#10482#>n<#10482#><#62237#> is a number and <#62238#><#10483#>lon<#10483#><#62238#> is a list of numbers.
Given that this data definition is self-referential again, we must first confirm that it actually defines some lists and that it defines all those inventories that we wish to represent. All of the examples from above are lists of numbers. The first one, <#62239#><#10486#>empty<#10486#><#62239#>, is included explicitly. The second and third are <#62240#><#10487#>cons<#10487#><#62240#>tructed by adding the numbers <#62241#><#10488#>1.22<#10488#><#62241#> and <#62242#><#10489#>2.59<#10489#><#62242#>, respectively, to the empty list. The others are lists of numbers for similar reasons. As always, we start the development of the function with a contract, header, and purpose statement:
<#70968#>;; <#62243#><#10494#>sum<#10494#> <#10495#>:<#10495#> <#10496#>list-of-numbers<#10496#> <#10497#><#10497#><#10498#>-;SPMgt;<#10498#><#10499#><#10499#> <#10500#>number<#10500#><#62243#><#70968#>
<#70969#>;; to compute the sum of the numbers on <#62244#><#10501#>a-list-of-nums<#10501#><#62244#><#70969#> 
<#10502#>(define<#10502#> <#10503#>(sum<#10503#> <#10504#>a-list-of-nums)<#10504#> <#10505#>...)<#10505#> 
Then we continue with function examples:
  <#10513#>(sum<#10513#> <#10514#>empty)<#10514#> 
<#10515#>=<#10515#> <#10516#>0<#10516#> 
  <#10524#>(sum<#10524#> <#10525#>(cons<#10525#> <#10526#>1.00<#10526#> <#10527#>empty))<#10527#>
<#10528#>=<#10528#> <#10529#>1.0<#10529#> 
  <#10537#>(sum<#10537#> <#10538#>(cons<#10538#> <#10539#>17.05<#10539#> <#10540#>(cons<#10540#> <#10541#>1.22<#10541#> <#10542#>(cons<#10542#> <#10543#>2.59<#10543#> <#10544#>empty))))<#10544#>
<#10545#>=<#10545#> <#10546#>20.86<#10546#> 
If <#62245#><#10550#>sum<#10550#><#62245#> is applied to <#62246#><#10551#>empty<#10551#><#62246#>, the store has no inventory and the result should be <#62247#><#10552#>0<#10552#><#62247#>. If the input is <#62248#><#10553#>(cons<#10553#>\ <#10554#>1.00<#10554#><#10555#> <#10555#><#10556#>empty)<#10556#><#62248#>, the inventory contains only one toy, and the cost of the toy is the cost of the inventory. Hence, the result is <#62249#><#10557#>1.00<#10557#><#62249#>. Finally, for <#62250#><#10558#>(cons<#10558#>\ <#10559#>17.05<#10559#>\ <#10560#>(cons<#10560#>\ <#10561#>1.22<#10561#>\ <#10562#>(cons<#10562#>\ <#10563#>2.59<#10563#>\ <#10564#>empty)))<#10564#><#62250#>, <#62251#><#10565#>sum<#10565#><#62251#> should yield

#displaymath72980#

For the design of <#62252#><#10566#>sum<#10566#><#62252#>'s template, we follow the design recipe, step by step. First, we add the <#62253#><#10567#>cond<#10567#>-expression<#62253#>:

<#10572#>(d<#10572#><#10573#>efine<#10573#> <#10574#>(sum<#10574#> <#10575#>a-list-of-nums)<#10575#>
  <#10576#>(c<#10576#><#10577#>ond<#10577#> 
    <#10578#>[<#10578#><#10579#>(empty?<#10579#> <#10580#>a-list-of-nums)<#10580#> <#10581#>...]<#10581#> 
    <#10582#>[<#10582#><#10583#>(cons?<#10583#> <#10584#>a-list-of-nums)<#10584#> <#10585#>...]<#10585#><#10586#>))<#10586#> 
The second clause indicates with a comment that it deals with <#62254#><#10590#>cons<#10590#><#62254#>tructed lists. Second, we add the appropriate selector expressions for each clause:
<#10595#>(d<#10595#><#10596#>efine<#10596#> <#10597#>(sum<#10597#> <#10598#>a-list-of-nums)<#10598#>
  <#10599#>(c<#10599#><#10600#>ond<#10600#> 
    <#10601#>[<#10601#><#10602#>(empty?<#10602#> <#10603#>a-list-of-nums)<#10603#> <#10604#>...]<#10604#> 
    <#10605#>[<#10605#><#10606#>(cons?<#10606#> <#10607#>a-list-of-nums)<#10607#> 
     <#10608#>...<#10608#> <#10609#>(first<#10609#> <#10610#>a-list-of-nums)<#10610#> <#10611#>...<#10611#> <#10612#>(rest<#10612#> <#10613#>a-list-of-nums)<#10613#> <#10614#>...]<#10614#><#10615#>))<#10615#> 
Finally, we add the natural recursion of <#62255#><#10619#>sum<#10619#><#62255#> that reflects the self-reference in the data definition:
<#10624#>(d<#10624#><#10625#>efine<#10625#> <#10626#>(sum<#10626#> <#10627#>a-list-of-nums)<#10627#>
  <#10628#>(c<#10628#><#10629#>ond<#10629#> 
    <#10630#>[<#10630#><#10631#>(empty?<#10631#> <#10632#>a-list-of-nums)<#10632#> <#10633#>...]<#10633#> 
    <#10634#>[<#10634#><#10635#>else<#10635#> <#10636#>...<#10636#> <#10637#>(first<#10637#> <#10638#>a-list-of-nums)<#10638#> <#10639#>...<#10639#> <#10640#>(sum<#10640#> <#10641#>(rest<#10641#> <#10642#>a-list-of-nums))<#10642#> <#10643#>...]<#10643#><#10644#>))<#10644#> 
The final template reflects almost every aspect of the data definition: the two clauses, the <#62256#><#10648#>cons<#10648#><#62256#>truction in the second clauses, and the self-reference of the second clauses. The only part of the data definition that the function template does not reflect is that the first item of a <#62257#><#10649#>cons<#10649#><#62257#>ed input is a number. Now that we have a template, let us define the answers for the <#62258#><#10650#>cond<#10650#>-expression<#62258#> on on a clause-by-clause basis. In the first clause, the input is <#62259#><#10651#>empty<#10651#><#62259#>, which means that the store has no inventory. We already agreed that in this case the inventory is worth nothing, which means the corresponding answer is <#62260#><#10652#>0<#10652#><#62260#>. In the second clause of the template, we find two expressions:
  1. <#62261#><#10654#>(first<#10654#>\ <#10655#>a-list-of-nums)<#10655#><#62261#>, which extracts the cost of the first toy; and
  2. <#62262#><#10656#>(sum<#10656#>\ <#10657#>(rest<#10657#>\ <#10658#>a-list-of-nums))<#10658#><#62262#>, which, according to the purpose statement of <#62263#><#10659#>sum<#10659#><#62263#>, computes the sum of <#62264#><#10660#>(rest<#10660#>\ <#10661#>a-list-of-nums)<#10661#><#62264#>.
From these two reminders of what the expressions already compute for us, we see that the expression
<#10667#>(+<#10667#> <#10668#>(first<#10668#> <#10669#>a-list-of-nums)<#10669#> <#10670#>(sum<#10670#> <#10671#>(rest<#10671#> <#10672#>a-list-of-nums)))<#10672#>
computes the answer in the second <#62265#><#10676#>cond<#10676#><#62265#>-clause. Here is the complete definition of <#62266#><#10677#>sum<#10677#><#62266#>:
<#10682#>(d<#10682#><#10683#>efine<#10683#> <#10684#>(sum<#10684#> <#10685#>a-list-of-nums)<#10685#>
  <#10686#>(c<#10686#><#10687#>ond<#10687#> 
    <#10688#>[<#10688#><#10689#>(empty?<#10689#> <#10690#>a-list-of-nums)<#10690#> <#10691#>0]<#10691#> 
    <#10692#>[<#10692#><#10693#>else<#10693#> <#10694#>(+<#10694#> <#10695#>(first<#10695#> <#10696#>a-list-of-nums)<#10696#> <#10697#>(sum<#10697#> <#10698#>(rest<#10698#> <#10699#>a-list-of-nums)))]<#10699#><#10700#>))<#10700#> 
A comparison of this definition with the template and the data definition shows that the step from the data definition to the template is the major step in the function development process. Once we have derived the template from a solid understanding of the set of possible inputs, we can focus on the creative part: combining values. For simple examples, this step is easy; for others, it requires rigorous thinking. We will see in future sections that this relationship between the shape of the data definition and the function is not a coincidence. Defining the class of data that a function consumes always determines to a large extent the shape of the function.
<#10706#>Exercise 9.5.1<#10706#> Use DrScheme to test the definition of <#62267#><#10708#>sum<#10708#><#62267#> on the following sample lists of numbers:
<#10713#>empty<#10713#> 
<#10714#>(cons<#10714#> <#10715#>1.00<#10715#> <#10716#>empty)<#10716#> 
<#10717#>(cons<#10717#> <#10718#>17.05<#10718#> <#10719#>(cons<#10719#> <#10720#>1.22<#10720#> <#10721#>(cons<#10721#> <#10722#>2.59<#10722#> <#10723#>empty)))<#10723#> 
Compare the results with our specifications. Then apply <#62268#><#10727#>sum<#10727#><#62268#> to the following examples:
<#10732#>empty<#10732#>
<#10733#>(cons<#10733#> <#10734#>2.59<#10734#> <#10735#>empty)<#10735#> 
<#10736#>(cons<#10736#> <#10737#>1.22<#10737#> <#10738#>(cons<#10738#> <#10739#>2.59<#10739#> <#10740#>empty))<#10740#> 
First determine what the result <#10744#>should<#10744#> be; then use DrScheme to evaluate the expressions. external Solution<#62269#><#62269#> <#10750#>Exercise 9.5.2<#10750#> Develop the function <#62270#><#10753#>how-many-symbols<#10753#><#62270#>, which consumes a list of symbols and produces the number of items in the list. Develop the function <#62271#><#10754#>how-many-numbers<#10754#><#62271#>, which counts how many numbers are in a list of numbers. How do <#62272#><#10755#>how-manyS<#10755#><#62272#> and <#62273#><#10756#>how-manyN<#10756#><#62273#> differ?~ external Solution<#62274#><#62274#> <#10762#>Exercise 9.5.3<#10762#> Develop the function <#62275#><#10764#>dollar-store?<#10764#><#62275#>, which consumes a list of prices (numbers) and checks whether all of the prices are below <#62276#><#10765#>1<#10765#><#62276#>. Examples:
  <#10770#>(dollar-store?<#10770#> <#10771#>empty)<#10771#>
<#10772#>=<#10772#> <#10773#>true<#10773#> 
  <#10781#>(dollar-store?<#10781#> <#10782#>(cons<#10782#> <#10783#>.75<#10783#> <#10784#>(cons<#10784#> <#10785#>1.95<#10785#> <#10786#>(cons<#10786#> <#10787#>.25<#10787#> <#10788#>empty))))<#10788#>
<#10789#>=<#10789#> <#10790#>false<#10790#> 
  <#10798#>(dollar-store?<#10798#> <#10799#>(cons<#10799#> <#10800#>.75<#10800#> <#10801#>(cons<#10801#> <#10802#>0.95<#10802#> <#10803#>(cons<#10803#> <#10804#>.25<#10804#> <#10805#>empty))))<#10805#>
<#10806#>=<#10806#> <#10807#>true<#10807#> 
Generalize the function so that it consumes a list of prices (numbers) and a threshold price (number) and checks that all prices in the list are below the threshold. external Solution<#62277#><#62277#> <#10816#>Exercise 9.5.4<#10816#> Develop the function <#62278#><#10818#>check-range1<#10818#><#62278#>, which consumes a list of temperature measurements and checks whether all measurements are between #tex2html_wrap_inline72982# and #tex2html_wrap_inline72984#. Generalize the function to <#62279#><#10819#>check-range<#10819#><#62279#>, which consumes a list of temperature measurements and a legal interval and checks whether all measurements are within the legal interval.~ external Solution<#62280#><#62280#> <#10825#>Exercise 9.5.5<#10825#> Develop the function <#62281#><#10827#>convert<#10827#><#62281#>. It consumes a list of digits and produces the corresponding number. The first digit is the least significant, and so on. Also develop the function <#62282#><#10828#>check-guess-for-list<#10828#><#62282#>. It implements a general version of the number guessing game of exercise~#exguess2#10829>. The function consumes a list of digits, which represents the player's <#62283#><#10830#>guess<#10830#><#62283#>, and a number, which represents the randomly chosen and hidden number. Depending on how the <#62284#><#10831#>convert<#10831#><#62284#>ed digits relate to <#62285#><#10832#>target<#10832#><#62285#>, <#62286#><#10833#>check-guess-for-list<#10833#><#62286#> produces one of the following three answers: <#62287#><#10834#>'<#10834#><#10835#>TooSmall<#10835#><#62287#>, <#62288#><#10836#>'<#10836#><#10837#>Perfect<#10837#><#62288#>, or <#62289#><#10838#>'<#10838#><#10839#>TooLarge<#10839#><#62289#>. The rest of the game is implemented by <#10840#>guess.ss<#10840#>. To play the game, use the teachpack to <#10841#>guess.ss<#10841#> and evaluate the expression
<#10846#>(repl-for-list<#10846#> <#10847#>5<#10847#> <#10848#>check-guess-for-list)<#10848#>
<#10852#>after<#10852#> the functions have been thoroughly developed.~ external Solution<#62290#><#62290#> <#10858#>Exercise 9.5.6<#10858#> Develop the function <#62291#><#10860#>delta<#10860#><#62291#>, which consumes two price lists, that is, lists of numbers. The first represents the inventory at the beginning of a time period, the second one the inventory at the end. The function outputs the difference in value. If the value of the inventory has increased, the result is positive; if the value has decreased, it is negative.~ external Solution<#62292#><#62292#> <#10866#>Exercise 9.5.7<#10866#> Define the function <#62293#><#10868#>average-price<#10868#><#62293#>. It consumes a list of toy prices and computes the average price of a toy. The average is the total of all prices divided by the number of toys. external ~<#10870#>This exercise is important. It shows that we must think about the design before we plunge in. One possibility is that students blindly follow the design recipe, without thinking about the concepts that the exercise involves. They should get stuck; some truly adventurous student may even solve it, but the solution will be overly complex. The better solution is to think ``domain'' knowledge: the average requires us to sum up the numbers and to count them. Then we decide. Two concepts means two auxiliary functions. Up to this point, students may have ignored our advice on auxiliary functions; this exercise drives home the point that auxiliary functions are a good idea. It all goes back to the standard hint of the previous part: ``Remember to develop auxiliary functions when a definition becomes too large or too complex to manage.''<#10870#>

<#10871#>Refinement<#10871#>:\ First develop a function that works on non-empty lists. Then produce a checked function (see section~#secinputerrors#10872>) that signals an error when the function is applied to an empty list.~ external Solution<#62294#><#62294#> <#10878#>Exercise 9.5.8<#10878#> Develop the function <#62295#><#10880#>draw-circles<#10880#><#62295#>, which consumes a <#62296#><#10881#>posn<#10881#><#62296#> <#62297#><#10882#>p<#10882#><#62297#> and a list of numbers. Each number of the list represents the radius of some circle. The function draws concentric red circles around <#62298#><#10883#>p<#10883#><#62298#> on a canvas, using the operation <#62299#><#10884#>draw-circle<#10884#><#62299#>. Its result is <#62300#><#10885#>true<#10885#><#62300#>, if it can draw all of them; otherwise an error occurred and the function does not need to produce a value. Use the teachpack <#10886#>draw.ss<#10886#>; create the canvas with <#62301#><#10887#>(start<#10887#>\ <#10888#>300<#10888#><#10889#> <#10889#><#10890#>300)<#10890#><#62301#>. Recall that <#10891#>draw.ss<#10891#> provides the structure definition for <#62302#><#10892#>posn<#10892#><#62302#> (see section~#secmixeddatapred#10893>).~ external Solution<#62303#><#62303#>