<#27052#>(define-struct<#27052#> <#27053#>ir<#27053#> <#27054#>(name<#27054#> <#27055#>price))<#27055#>
An <#65043#><#27060#>IR<#27060#><#65043#> is a structure:Given the similarity between the data definitions, functions that consume elements of these classes are similar, too. Take a look at the illustrative example in figure~#figcmpabovebelow2#27067>
<#71246#><#65044#><#27061#>(make-ir<#27061#>\ <#27062#>n<#27062#>\ <#27063#>p)<#27063#><#65044#><#71246#> where <#65045#><#27064#>n<#27064#><#65045#> is a symbol and <#65046#><#27065#>p<#27065#><#65046#> is a number.
<#71247#>;; <#65049#><#27074#>below<#27074#> <#27075#>:<#27075#> <#27076#>number<#27076#> <#27077#>lon<#27077#> <#27078#><#27078#><#27079#>-;SPMgt;<#27079#><#27080#><#27080#> <#27081#>lon<#27081#><#65049#><#71247#> <#27082#>;; to construct a list of those numbers<#27082#> <#71248#>;; on <#65050#><#27083#>alon<#27083#><#65050#> that are below <#65051#><#27084#>t<#27084#><#65051#><#71248#> <#27085#>(d<#27085#><#27086#>efine<#27086#> <#27087#>(below<#27087#> <#27088#>alon<#27088#> <#27089#>t)<#27089#> <#27090#>(c<#27090#><#27091#>ond<#27091#> <#27092#>[<#27092#><#27093#>(empty?<#27093#> <#27094#>alon)<#27094#> <#27095#>empty]<#27095#> <#27096#>[<#27096#><#27097#>else<#27097#> <#27098#>(c<#27098#><#27099#>ond<#27099#> <#27100#>[<#27100#><#27101#>(<#27101#>#tex2html_wrap73220# <#27103#>(first<#27103#> <#27104#>alon)<#27104#> <#27105#>t)<#27105#> <#27106#>(c<#27106#><#27107#>ons<#27107#> <#27108#>(first<#27108#> <#27109#>alon)<#27109#> <#27110#>(below<#27110#> <#27111#>(rest<#27111#> <#27112#>alon)<#27112#> <#27113#>t))]<#27113#> <#27114#>[<#27114#><#27115#>e<#27115#><#27116#>lse<#27116#> <#27117#>(below<#27117#> <#27118#>(rest<#27118#> <#27119#>alon)<#27119#> <#27120#>t)]<#27120#><#27121#>)]<#27121#><#27122#>))<#27122#>
<#71249#>;; <#65052#><#27128#>below-ir<#27128#> <#27129#>:<#27129#> <#27130#>number<#27130#> <#27131#>loIR<#27131#> <#27132#><#27132#><#27133#>-;SPMgt;<#27133#><#27134#><#27134#> <#27135#>loIR<#27135#><#65052#><#71249#> <#27136#>;; to construct a list of those records <#27136#> <#71250#>;; on <#65053#><#27137#>aloir<#27137#><#65053#> that contain a price below <#65054#><#27138#>t<#27138#><#65054#><#71250#> <#27139#>(d<#27139#><#27140#>efine<#27140#> <#27141#>(below<#27141#> <#27142#>aloir<#27142#> <#27143#>t)<#27143#> <#27144#>(c<#27144#><#27145#>ond<#27145#> <#27146#>[<#27146#><#27147#>(empty?<#27147#> <#27148#>aloir)<#27148#> <#27149#>empty]<#27149#> <#27150#>[<#27150#><#27151#>else<#27151#> <#27152#>(c<#27152#><#27153#>ond<#27153#> <#27154#>[<#27154#><#27155#>(<#27155#><#27198#>Figure: Marking the differences in similar functions<#27198#>#tex2html_wrap73222# <#27157#>(first<#27157#> <#27158#>aloir)<#27158#> <#27159#>t)<#27159#> <#27160#>(<#27160#><#27161#>cons<#27161#> <#27162#>(first<#27162#> <#27163#>aloir)<#27163#> <#27164#>(below-ir<#27164#> <#27165#>(rest<#27165#> <#27166#>aloir)<#27166#> <#27167#>t))]<#27167#> <#27168#>[<#27168#><#27169#>e<#27169#><#27170#>lse<#27170#> <#27171#>(below-ir<#27171#> <#27172#>(rest<#27172#> <#27173#>aloir)<#27173#> <#27174#>t)]<#27174#><#27175#>)]<#27175#><#27176#>))<#27176#> <#71251#>;; <#65056#> #tex2html_wrap_inline73210# <#27178#>:<#27178#> <#27179#>IR<#27179#> <#27180#>number<#27180#> <#27181#><#27181#><#27182#>-;SPMgt;<#27182#><#27183#><#27183#> <#27184#>boolean<#27184#><#65056#><#71251#> <#27185#>(def<#27185#><#27186#>ine<#27186#> <#27187#>(<#27187#> #tex2html_wrap_inline73212# <#27189#>ir<#27189#> <#27190#>p)<#27190#> <#27191#>(;SPMlt;<#27191#> <#27192#>(ir-price<#27192#> <#27193#>ir)<#27193#> <#27194#>p))<#27194#>
<#27207#>(d<#27207#><#27208#>efine<#27208#> <#27209#>(below-ir1<#27209#> <#27210#>aloir<#27210#> <#27211#>t)<#27211#> <#27212#>(filter1<#27212#>It should not surprise us to discover yet another use for <#65060#><#27219#>filter1<#27219#><#65060#>---after all, we already argued that abstraction promotes the re-use of functions for different purposes. Here we see that <#65061#><#27220#>filter1<#27220#><#65061#> not only filters lists of numbers but lists of arbitrary things---as long as we can define a function that compares these arbitrary things with numbers. Indeed, all we need is a function that compares items on the list with the items we pass to <#65062#><#27221#>filter1<#27221#><#65062#> as the second argument. Here is a function that extracts all items with the same label from a list of inventory records:#tex2html_wrap_inline73214# <#27214#>aloir<#27214#> <#27215#>t))<#27215#>
<#71252#>;; <#65063#><#27226#>find<#27226#> <#27227#>:<#27227#> <#27228#>loIR<#27228#> <#27229#>symbol<#27229#> <#27230#><#27230#><#27231#>-;SPMgt;<#27231#><#27232#><#27232#> <#27233#>boolean<#27233#><#65063#><#71252#> <#71253#>;; to determine whether <#65064#><#27234#>aloir<#27234#><#65064#> contains a record for <#65065#><#27235#>t<#27235#><#65065#><#71253#> <#27236#>(d<#27236#><#27237#>efine<#27237#> <#27238#>(find<#27238#> <#27239#>aloir<#27239#> <#27240#>t)<#27240#> <#27241#>(cons?<#27241#> <#27242#>(filter1<#27242#> <#27243#>eq-ir?<#27243#> <#27244#>aloir<#27244#> <#27245#>t)))<#27245#> <#71254#>;; <#65066#><#27246#>eq-ir?<#27246#> <#27247#>:<#27247#> <#27248#>IR<#27248#> <#27249#>symbol<#27249#> <#27250#><#27250#><#27251#>-;SPMgt;<#27251#><#27252#><#27252#> <#27253#>boolean<#27253#><#65066#><#71254#> <#71255#>;; to compare <#65067#><#27254#>ir<#27254#><#65067#>'s name and <#65068#><#27255#>p<#27255#><#65068#><#71255#> <#27256#>(d<#27256#><#27257#>efine<#27257#> <#27258#>(eq-ir?<#27258#> <#27259#>ir<#27259#> <#27260#>p)<#27260#> <#27261#>(symbol=?<#27261#> <#27262#>(ir-name<#27262#> <#27263#>ir)<#27263#> <#27264#>p))<#27264#>This new relational operator compares the name in an inventory record with some other symbol.
<#71256#>;; <#65082#><#27322#>length-lon<#27322#> <#27323#>:<#27323#> <#27324#>lon<#27324#> <#27325#><#27325#><#27326#>-;SPMgt;<#27326#><#27327#><#27327#> <#27328#>number<#27328#><#65082#><#71256#> <#27329#>(d<#27329#><#27330#>efine<#27330#> <#27331#>(length-lon<#27331#> <#27332#>alon)<#27332#> <#27333#>(c<#27333#><#27334#>ond<#27334#> <#27335#>[<#27335#><#27336#>(empty?<#27336#> <#27337#>alon)<#27337#> <#27338#>empty]<#27338#> <#27339#>[<#27339#><#27340#>e<#27340#><#27341#>lse<#27341#> <#27342#>(+<#27342#> <#27343#>(length-lon<#27343#> <#27344#>(rest<#27344#> <#27345#>alon))<#27345#> <#27346#>1)]<#27346#><#27347#>))<#27347#>
<#71257#>;; <#65083#><#27353#>length-ir<#27353#> <#27354#>:<#27354#> <#27355#>loIR<#27355#> <#27356#><#27356#><#27357#>-;SPMgt;<#27357#><#27358#><#27358#> <#27359#>number<#27359#><#65083#><#71257#> <#27360#>(d<#27360#><#27361#>efine<#27361#> <#27362#>(length-ir<#27362#> <#27363#>alon)<#27363#> <#27364#>(c<#27364#><#27365#>ond<#27365#> <#27366#>[<#27366#><#27367#>(empty?<#27367#> <#27368#>alon)<#27368#> <#27369#>empty]<#27369#> <#27370#>[<#27370#><#27371#>e<#27371#><#27372#>lse<#27372#> <#27373#>(+<#27373#> <#27374#>(length-ir<#27374#> <#27375#>(rest<#27375#> <#27376#>alon))<#27376#> <#27377#>1)]<#27377#><#27378#>))<#27378#>The two functions only differ in their names. If we had chosen the same name, say <#65084#><#27382#>length<#27382#><#65084#>, the two definitions would be identical. To write precise contracts for functions such as <#65085#><#27383#>length<#27383#><#65085#>, we need <#27384#>parametric data definitions<#27384#>. A <#65086#><#27385#>PARAMETRIC DATA DEFINITION<#27385#><#65086#> does not specify all pieces of data; instead it uses variables to say that <#27386#> any<#27386#> form of Scheme data can be used in a certain place. Roughly speaking, a parametric data definition abstracts from a reference to a particular collection of data in the same manner as a function abstracts from a particular value. Here is a parametric definition of lists of <#65087#><#27387#>ITEM<#27387#><#65087#>s:
A <#65088#><#27389#>list of ITEM<#27389#><#65088#> is eitherThe token <#65093#><#27404#>ITEM<#27404#><#65093#> is a <#65094#><#27405#>TYPE VARIABLE<#27405#><#65094#> that stands for any arbitrary collection of Scheme data: symbols, numbers, booleans, <#65095#><#27406#>IR<#27406#><#65095#>s, etc. By replacing <#65096#><#27407#>ITEM<#27407#><#65096#> with one of these names, we get a concrete instance of this abstract data definition for lists of symbols, numbers, booleans, <#65097#><#27408#>IR<#27408#><#65097#>s, etc. To make the language of contracts more concise, we introduce an additional abbreviation:
- <#65089#><#27391#>empty<#27391#><#65089#> or
- <#65090#><#27392#>(cons<#27392#>\ <#27393#>s<#27393#>\ <#27394#>l)<#27394#><#65090#> where
- <#65091#><#27396#>s<#27396#><#65091#> is
#tex2html_wrap73224# and - <#65092#><#27398#>l<#27398#><#65092#> is a list of ITEM.~
<#27413#>(listof<#27413#> <#27414#>ITEM)<#27414#>We use <#65098#><#27418#>(listof<#27418#>\ <#27419#>ITEM)<#27419#><#65098#> as the name of abstract data definitions like the above. In other words, we define <#65099#><#27420#>(listof<#27420#>\ <#27421#>ITEM)<#27421#><#65099#> as follows:
A <#72240#><#71258#><#65100#><#27423#>(listof<#27423#>\ <#27424#>ITEM)<#27424#><#65100#><#71258#><#72240#> is eitherThen we can use <#65107#><#27441#>(listof<#27441#>\ <#27442#>symbol)<#27442#><#65107#> for the class of all lists of symbols, <#65108#><#27443#>(listof<#27443#>\ <#27444#>number)<#27444#><#65108#> for the class of all lists of numbers, <#65109#><#27445#>(listof<#27445#>\ <#27446#>(listof<#27446#>\ <#27447#>number))<#27447#><#65109#> for the class of all lists of lists of numbers, <#27448#>etc<#27448#>. In contracts, we use <#65110#><#27449#>(listof<#27449#>\ <#27450#>X)<#27450#><#65110#> to say that the function works on arbitrary lists:
- <#65101#><#27426#>empty<#27426#><#65101#> or
- <#65102#><#27427#>(cons<#27427#>\ <#27428#>s<#27428#>\ <#27429#>l)<#27429#><#65102#> where
- <#65103#><#27431#>s<#27431#><#65103#> is
#tex2html_wrap73226# and - <#65105#><#27433#>l<#27433#><#65105#> is a <#65106#><#27434#>(listof<#27434#>\ <#27435#>ITEM)<#27435#><#65106#>.~
<#71260#>;; <#65111#><#27455#>length<#27455#> <#27456#>:<#27456#> <#27457#>(listof<#27457#> <#27458#>X)<#27458#> <#27459#><#27459#><#27460#>-;SPMgt;<#27460#><#27461#><#27461#> <#27462#>number<#27462#><#65111#><#71260#> <#27463#>;; to compute the length of a list <#27463#> <#27464#>(d<#27464#><#27465#>efine<#27465#> <#27466#>(length<#27466#> <#27467#>alon)<#27467#> <#27468#>(c<#27468#><#27469#>ond<#27469#> <#27470#>[<#27470#><#27471#>(empty?<#27471#> <#27472#>alon)<#27472#> <#27473#>empty]<#27473#> <#27474#>[<#27474#><#27475#>else<#27475#> <#27476#>(+<#27476#> <#27477#>(length<#27477#> <#27478#>(rest<#27478#> <#27479#>alon))<#27479#> <#27480#>1)]<#27480#><#27481#>))<#27481#>The <#65112#><#27485#>X<#27485#><#65112#> is just a variable, a name that stands for some class of data. If we now apply <#65113#><#27486#>length<#27486#><#65113#> to an element of, say, <#65114#><#27487#>(listof<#27487#>\ <#27488#>symbol)<#27488#><#65114#> or <#65115#><#27489#>(listof<#27489#>\ <#27490#>IR)<#27490#><#65115#>, we get a number. The function <#65116#><#27491#>length<#27491#><#65116#> is an example of simple polymorphism. It works on all classes of lists. While there are other useful examples of simple polymorphic functions, the more common cases require that we define functions like <#65117#><#27492#>filter1<#27492#><#65117#>, which consume a parametric form of data and functions that work on this data. This combination is extremely powerful and greatly facilitates the construction and maintenance of software systems. To understand it better, we will next discuss a revision of Scheme's grammar and new ways to write contracts.
<#27511#>(define-struct<#27511#> <#27512#>pair<#27512#> <#27513#>(left<#27513#> <#27514#>right))<#27514#>and its parametric data definition:
A <#72241#><#71261#>(pair <#65121#><#27519#>X<#27519#><#65121#> <#65122#><#27520#>Y<#27520#><#65122#>)<#71261#><#72241#> is a structure:Using this abstract data definition, we can describe many different forms of pairs:
<#71262#><#65123#><#27521#>(make-pair<#27521#>\ <#27522#>l<#27522#>\ <#27523#>r)<#27523#><#65123#><#71262#> where <#65124#><#27524#>l<#27524#><#65124#> is an <#65125#><#27525#>X<#27525#><#65125#> and <#65126#><#27526#>r<#27526#><#65126#> is a <#65127#><#27527#>Y<#27527#><#65127#>.
<#71263#> <#65133#><#27542#>(listof<#27542#>\ <#27543#>(pair<#27543#>\ <#27544#>X<#27544#>\ <#27545#>Y))<#27545#><#65133#> \ .<#71263#> Some concrete examples of this abstract class of data are:
<#72343#>A <#72242#><#71264#><#65142#><#27574#>(non-empty-listof<#27574#>\ <#27575#>ITEM)<#27575#><#65142#><#71264#><#72242#> is eitherDevelop the function <#65149#><#27590#>last<#27590#><#65149#>, which consumes a <#65150#><#27591#>(non-empty-listof<#27591#>\ <#27592#>ITEM)<#27592#><#65150#> and produces the last <#65151#><#27593#>ITEM<#27593#><#65151#> in that list. <#27594#>Hint:<#27594#> \ Replace <#65152#><#27595#>ITEM<#27595#><#65152#> with a fixed class of data to develop an initial draft of <#65153#><#27596#>last<#27596#><#65153#>. When finished, replace the class with <#65154#><#27597#>ITEM<#27597#><#65154#> throughout the function development.~ Solution<#65155#><#65155#><#72343#> and <#65147#><#27587#>s<#27587#><#65147#> is always an <#65148#><#27588#>ITEM<#27588#><#65148#>.
- <#65143#><#27577#>(cons<#27577#>\ <#27578#>s<#27578#>\ <#27579#>empty)<#27579#><#65143#>, or
- <#65144#><#27580#>(cons<#27580#>\ <#27581#>s<#27581#>\ <#27582#>l)<#27582#><#65144#> where <#65145#><#27583#>l<#27583#><#65145#> is a <#65146#><#27584#>(non-empty-listof<#27584#>\ <#27585#>ITEM)<#27585#><#65146#>