<#11496#>(define-struct<#11496#> <#11497#>ir<#11497#> <#11498#>(name<#11498#> <#11499#>price))<#11499#>
An <#62412#><#11504#>inventory record<#11504#><#62412#> (<#62413#><#11505#>ir<#11505#><#62413#>) is a structure:Most importantly, we can define a class of lists that represent an inventory much more realistically:
<#70982#> <#62414#><#11506#>(make-ir<#11506#>\ <#11507#>s<#11507#>\ <#11508#>n)<#11508#><#62414#> <#70982#>
where <#62415#><#11509#>s<#11509#><#62415#> is a symbol and <#62416#><#11510#>n<#11510#><#62416#> is a (positive) number.
An <#62417#><#11513#>inventory<#11513#><#62417#> is eitherWhile the shape of the list definition is the same as before, its components are defined in a separate data definition. Since this is our first such data definition, we should make up some examples before we proceed. The simplest example of an inventory is <#62422#><#11523#>empty<#11523#><#62422#>. To create a larger inventory, we must create an inventory record and <#62423#><#11524#>cons<#11524#><#62423#> it onto another inventory:
- <#62418#><#11515#>empty<#11515#><#62418#> or
- <#62419#><#11516#>(cons<#11516#>\ <#11517#>ir<#11517#>\ <#11518#>inv)<#11518#><#62419#>
where <#62420#><#11519#>ir<#11519#><#62420#> is an inventory record and <#62421#><#11520#>inv<#11520#><#62421#> is an inventory.
<#11529#>(c<#11529#><#11530#>ons<#11530#> <#11531#>(make-ir<#11531#> <#11532#>'<#11532#><#11533#>doll<#11533#> <#11534#>17.95)<#11534#> <#11535#>empty)<#11535#>From here, we can create yet a larger inventory listing:
<#11543#>(c<#11543#><#11544#>ons<#11544#> <#11545#>(make-ir<#11545#> <#11546#>'<#11546#><#11547#>robot<#11547#> <#11548#>22.05)<#11548#> <#11549#>(c<#11549#><#11550#>ons<#11550#> <#11551#>(make-ir<#11551#> <#11552#>'<#11552#><#11553#>doll<#11553#> <#11554#>17.95)<#11554#> <#11555#>empty))<#11555#>Now we can adapt our inventory-processing functions. First look at <#62424#><#11559#>sum<#11559#><#62424#>, the function that consumes an inventory and produces its total value. Here is a re-statement of the basic information about the function:
<#70983#>;; <#62425#><#11564#>sum<#11564#> <#11565#>:<#11565#> <#11566#>inventory<#11566#> <#11567#><#11567#><#11568#>-;SPMgt;<#11568#><#11569#><#11569#> <#11570#>number<#11570#><#62425#><#70983#> <#70984#>;; to compute the sum of prices on <#62426#><#11571#>an-inv<#11571#><#62426#><#70984#> <#11572#>(define<#11572#> <#11573#>(sum<#11573#> <#11574#>an-inv)<#11574#> <#11575#>...)<#11575#>For our three sample inventories, the function should produce the following results: <#62427#><#11579#>0<#11579#><#62427#>, <#62428#><#11580#>17.95<#11580#><#62428#>, and <#62429#><#11581#>40.0<#11581#><#62429#>. Since the data definition of inventories is basically that of lists, we can again start from the template for list-processing functions:
<#11586#>(d<#11586#><#11587#>efine<#11587#> <#11588#>(sum<#11588#> <#11589#>an-inv)<#11589#> <#11590#>(c<#11590#><#11591#>ond<#11591#> <#11592#>[<#11592#><#11593#>(empty?<#11593#> <#11594#>an-inv)<#11594#> <#11595#>...]<#11595#> <#11596#>[<#11596#><#11597#>else<#11597#> <#11598#>...<#11598#> <#11599#>(first<#11599#> <#11600#>an-inv)<#11600#> <#11601#>...<#11601#> <#11602#>(sum<#11602#> <#11603#>(rest<#11603#> <#11604#>an-inv))<#11604#> <#11605#>...]<#11605#><#11606#>))<#11606#>Following our recipe, the template only reflects the data definition of the input, not that of its constituents. Therefore the template for <#62430#><#11610#>sum<#11610#><#62430#> here is indistinguishable from that in section~#seclistsmore#11611>
<#11623#>(d<#11623#><#11624#>efine<#11624#> <#11625#>(sum<#11625#> <#11626#>an-inv)<#11626#> <#11627#>(c<#11627#><#11628#>ond<#11628#> <#11629#>[<#11629#><#11630#>(empty?<#11630#> <#11631#>an-inv)<#11631#> <#11632#>0]<#11632#> <#11633#>[<#11633#><#11634#>else<#11634#> <#11635#>(+<#11635#> <#11636#>(ir-price<#11636#> <#11637#>(first<#11637#> <#11638#>an-inv))<#11638#> <#11639#>(sum<#11639#> <#11640#>(rest<#11640#> <#11641#>an-inv)))]<#11641#><#11642#>))<#11642#><#11646#>Figure: Computing the value of an inventory<#11646#>
<#11668#>(+<#11668#> <#11669#>(ir-price<#11669#> <#11670#>(first<#11670#> <#11671#>an-inv))<#11671#> <#11672#>(sum<#11672#> <#11673#>(rest<#11673#> <#11674#>an-inv)))<#11674#>The complete function definition is contained in figure~#figsumir#11678>
<#70985#>;; <#62447#><#11688#>contains-doll?<#11688#> <#11689#>:<#11689#> <#11690#>inventory<#11690#> <#11691#><#11691#><#11692#>-;SPMgt;<#11692#><#11693#><#11693#> <#11694#>boolean<#11694#><#62447#><#70985#> <#70986#>;; to determine whether <#62448#><#11695#>an-inv<#11695#><#62448#> contains a record for <#62449#><#11696#>'<#11696#><#11697#>doll<#11697#><#62449#><#70986#> <#11698#>(define<#11698#> <#11699#>(contains-doll?<#11699#> <#11700#>an-inv)<#11700#> <#11701#>...)<#11701#>Also adapt the function <#62450#><#11705#>contains?<#11705#><#62450#>, which consumes a symbol and an inventory and determines whether an inventory record with this symbol occurs in the inventory:
<#70987#>;; <#62451#><#11710#>contains?<#11710#> <#11711#>:<#11711#> <#11712#>symbol<#11712#> <#11713#>inventory<#11713#> <#11714#><#11714#><#11715#>-;SPMgt;<#11715#><#11716#><#11716#> <#11717#>boolean<#11717#><#62451#><#70987#> <#70988#>;; to determine whether <#62452#><#11718#>inventory<#11718#><#62452#> contains a record for <#62453#><#11719#>asymbol<#11719#><#62453#><#70988#> <#11720#>(define<#11720#> <#11721#>(contains?<#11721#> <#11722#>asymbol<#11722#> <#11723#>an-inv)<#11723#> <#11724#>...)<#11724#>Solution<#62454#><#62454#>
Suppose a business wishes to separate all those items that sell for a dollar or less from all others. The goal might be to sell these items in a separate department of the store. To perform this split, the business also needs a function that can extract these items from its inventory listing, <#11767#>i.e.<#11767#>, a function that produces a list of structures. Let us name the function <#62463#><#11768#>extract1<#11768#><#62463#> because it creates an inventory from all those inventory records whose price item is less than or equal to <#62464#><#11769#>1.00<#11769#><#62464#>. The function consumes an inventory and produces one with items of appropriate prices. Thus the contract for <#62465#><#11770#>extract1<#11770#><#62465#> is easy to formulate:
<#70989#>;; <#62466#><#11775#>extract1<#11775#> <#11776#>:<#11776#> <#11777#>inventory<#11777#> <#11778#><#11778#><#11779#>-;SPMgt;<#11779#><#11780#><#11780#> <#11781#>inventory<#11781#><#62466#><#70989#> <#70990#>;; to create an <#62467#><#11782#>inventory<#11782#><#62467#> from <#62468#><#11783#>an-inv<#11783#><#62468#> for all<#70990#> <#11784#>;; those items that cost less than $1<#11784#> <#11785#>(define<#11785#> <#11786#>(extract1<#11786#> <#11787#>an-inv)<#11787#> <#11788#>...)<#11788#>We can reuse our old inventory examples to make examples of <#62469#><#11792#>extract1<#11792#><#62469#>'s input-output relationship. Unfortunately, it must produce the empty inventory, for the three examples that we used above because all prices are above one dollar. For a more interesting input-output example, we need an inventory with more variety:
<#11797#>(cons<#11797#> <#11798#>(make-ir<#11798#> <#11799#>'<#11799#><#11800#>dagger<#11800#> <#11801#>.95)<#11801#> <#11802#>(cons<#11802#> <#11803#>(make-ir<#11803#> <#11804#>'<#11804#><#11805#>Barbie<#11805#> <#11806#>17.95)<#11806#> <#11807#>(cons<#11807#> <#11808#>(make-ir<#11808#> <#11809#>'<#11809#><#11810#>key-chain<#11810#> <#11811#>.55)<#11811#> <#11812#>(cons<#11812#> <#11813#>(make-ir<#11813#> <#11814#>'<#11814#><#11815#>robot<#11815#> <#11816#>22.05)<#11816#> <#11817#>empty))))<#11817#>Out of the four items in this new inventory, two have prices below one dollar. If given to <#62470#><#11821#>extract1<#11821#><#62470#>, we should get the result
<#11826#>(cons<#11826#> <#11827#>(make-ir<#11827#> <#11828#>'<#11828#><#11829#>dagger<#11829#> <#11830#>.95)<#11830#> <#11831#>(cons<#11831#> <#11832#>(make-ir<#11832#> <#11833#>'<#11833#><#11834#>key-chain<#11834#> <#11835#>.55)<#11835#> <#11836#>empty))<#11836#>The new listing enumerates the items in the same order as the original, but only contains those items whose prices match our condition. The contract also implies that the template for <#62471#><#11840#>extract1<#11840#><#62471#> is identical to that of <#62472#><#11841#>sum<#11841#><#62472#>, except for a name change:
<#11846#>(d<#11846#><#11847#>efine<#11847#> <#11848#>(extract1<#11848#> <#11849#>an-inv)<#11849#> <#11850#>(c<#11850#><#11851#>ond<#11851#> <#11852#>[<#11852#><#11853#>(empty?<#11853#> <#11854#>an-inv)<#11854#> <#11855#>...]<#11855#> <#11856#>[<#11856#><#11857#>else<#11857#> <#11858#>...<#11858#> <#11859#>(first<#11859#> <#11860#>an-inv)<#11860#> <#11861#>...<#11861#> <#11862#>(extract1<#11862#> <#11863#>(rest<#11863#> <#11864#>an-inv))<#11864#> <#11865#>...]<#11865#><#11866#>))<#11866#>As always, the difference in outputs between <#62473#><#11870#>sum<#11870#><#62473#> and <#62474#><#11871#>extract1<#11871#><#62474#> does not affect the template derivation.
<#70991#>;; <#62475#><#11876#>extract1<#11876#> <#11877#>:<#11877#> <#11878#>inventory<#11878#> <#11879#><#11879#><#11880#>-;SPMgt;<#11880#><#11881#><#11881#> <#11882#>inventory<#11882#><#62475#><#70991#> <#70992#>;; to create an <#62476#><#11883#>inventory<#11883#><#62476#> from <#62477#><#11884#>an-inv<#11884#><#62477#> for all<#70992#> <#11885#>;; those items that cost less than $1<#11885#> <#11886#>(d<#11886#><#11887#>efine<#11887#> <#11888#>(extract1<#11888#> <#11889#>an-inv)<#11889#> <#11890#>(c<#11890#><#11891#>ond<#11891#> <#11892#>[<#11892#><#11893#>(empty?<#11893#> <#11894#>an-inv)<#11894#> <#11895#>empty]<#11895#> <#11896#>[<#11896#><#11897#>else<#11897#> <#11898#>(c<#11898#><#11899#>ond<#11899#> <#11900#>[<#11900#><#11901#>(;SPMlt;=<#11901#> <#11902#>(ir-price<#11902#> <#11903#>(first<#11903#> <#11904#>an-inv))<#11904#> <#11905#>1.00)<#11905#> <#11906#>(cons<#11906#> <#11907#>(first<#11907#> <#11908#>an-inv)<#11908#> <#11909#>(extract1<#11909#> <#11910#>(rest<#11910#> <#11911#>an-inv)))]<#11911#> <#11912#>[<#11912#><#11913#>else<#11913#> <#11914#>(extract1<#11914#> <#11915#>(rest<#11915#> <#11916#>an-inv))]<#11916#><#11917#>)]<#11917#><#11918#>))<#11918#><#11922#>Figure: Extracting dollar items from an inventory<#11922#>
<#11933#>(cons<#11933#> <#11934#>(make-ir<#11934#> <#11935#>'<#11935#><#11936#>dagger<#11936#> <#11937#>.95)<#11937#> <#11938#>(cons<#11938#> <#11939#>(make-ir<#11939#> <#11940#>'<#11940#><#11941#>Barbie<#11941#> <#11942#>17.95)<#11942#> <#11943#>(cons<#11943#> <#11944#>(make-ir<#11944#> <#11945#>'<#11945#><#11946#>key-chain<#11946#> <#11947#>.55)<#11947#> <#11948#>(cons<#11948#> <#11949#>(make-ir<#11949#> <#11950#>'<#11950#><#11951#>robot<#11951#> <#11952#>22.05)<#11952#> <#11953#>empty))))<#11953#>If <#62482#><#11957#>an-inv<#11957#><#62482#> stands for this inventory,
<#11962#>(first<#11962#> <#11963#>an-inv)<#11963#> <#11964#>=<#11964#> <#11965#>(make-ir<#11965#> <#11966#>'<#11966#><#11967#>dagger<#11967#> <#11968#>.95)<#11968#> <#11969#>(rest<#11969#> <#11970#>an-inv)<#11970#> <#11971#>=<#11971#> <#11972#>(cons<#11972#> <#11973#>(make-ir<#11973#> <#11974#>'<#11974#><#11975#>Barbie<#11975#> <#11976#>17.95)<#11976#> <#11977#>(cons<#11977#> <#11978#>(make-ir<#11978#> <#11979#>'<#11979#><#11980#>key-chain<#11980#> <#11981#>.55)<#11981#> <#11982#>(c<#11982#><#11983#>ons<#11983#> <#11984#>(make-ir<#11984#> <#11985#>'<#11985#><#11986#>robot<#11986#> <#11987#>22.05)<#11987#> <#11988#>empty)))<#11988#>Assuming <#62483#><#11992#>extract1<#11992#><#62483#> works correctly, we also know that
<#11997#>(extract1<#11997#> <#11998#>(rest<#11998#> <#11999#>an-inv))<#11999#> <#12000#>=<#12000#> <#12001#>(c<#12001#><#12002#>ons<#12002#> <#12003#>(make-ir<#12003#> <#12004#>'<#12004#><#12005#>key-chain<#12005#> <#12006#>.55)<#12006#> <#12007#>empty)<#12007#>In other words, the recursive application of <#62484#><#12011#>extract1<#12011#><#62484#> produces the appropriate selection from the rest of <#62485#><#12012#>an-inv<#12012#><#62485#>, which is a list with a single inventory record. To produce an appropriate inventory for all of <#62486#><#12013#>an-inv<#12013#><#62486#>, we must decide what to do with the first item. Its price may be more or less than one dollar, which suggest the following template for the second answer:
<#12018#>...<#12018#> <#12019#>(c<#12019#><#12020#>ond<#12020#> <#12021#>[<#12021#><#12022#>(;SPMlt;=<#12022#> <#12023#>(ir-price<#12023#> <#12024#>(first<#12024#> <#12025#>an-inv))<#12025#> <#12026#>1.00)<#12026#> <#12027#>...]<#12027#> <#12028#>[<#12028#><#12029#>else<#12029#> <#12030#>...]<#12030#><#12031#>)<#12031#> <#12032#>...<#12032#>If the first item's price is one dollar or less, it must be included in the final output and, according to our example, should be the first item on the output. Translated into Scheme, the output should be a list whose first item is <#62487#><#12036#>(first<#12036#>\ <#12037#>an-inv)<#12037#><#62487#> and whose rest is whatever the recursion produces. If the price is more than one dollar, the item should not be included. That is, the result should be whatever the recursion produces for the <#62488#><#12038#>rest<#12038#><#62488#> of <#62489#><#12039#>an-inv<#12039#><#62489#> and nothing else. The complete definition is displayed in figure~#figextract1#12040>
<#70993#>;; <#62493#><#12058#>extract1<#12058#> <#12059#>:<#12059#> <#12060#>inventory<#12060#> <#12061#><#12061#><#12062#>-;SPMgt;<#12062#><#12063#><#12063#> <#12064#>inventory1<#12064#><#62493#><#70993#> <#12065#>(define<#12065#> <#12066#>(extract1<#12066#> <#12067#>an-inv)<#12067#> <#12068#>...)<#12068#>Does the refined contract affect the development of the function above? Solution<#62494#><#62494#> <#12077#>Exercise 10.2.7<#12077#>