<#28239#>Warning: Abstracting over Non-values<#28239#>:\ <#28240#>The recipe requires a substantial modification for non-values.<#28240#>~<#65342#><#65342#> Here is a pair of similar function definitions:
<#71326#>;; <#65343#><#28247#>convertCF<#28247#> <#28248#>:<#28248#> <#28249#>lon<#28249#> <#28250#><#28250#><#28251#>-;SPMgt;<#28251#><#28252#><#28252#> <#28253#>lon<#28253#><#65343#><#71326#> <#28254#>(d<#28254#><#28255#>efine<#28255#> <#28256#>(convertCF<#28256#> <#28257#>alon)<#28257#> <#28258#>(c<#28258#><#28259#>ond<#28259#> <#28260#>[<#28260#><#28261#>(empty?<#28261#> <#28262#>alon)<#28262#> <#28263#>empty]<#28263#> <#28264#>[<#28264#><#28265#>e<#28265#><#28266#>lse<#28266#> <#28267#>(c<#28267#><#28268#>ons<#28268#> <#28269#>(<#28269#>#tex2html_wrap73320# <#28275#>(first<#28275#> <#28276#>alon))<#28276#> <#28277#>(convertCF<#28277#> <#28278#>(rest<#28278#> <#28279#>alon)))]<#28279#><#28280#>))<#28280#>
<#71328#>;; <#65345#><#28286#>names<#28286#> <#28287#>:<#28287#> <#28288#>loIR<#28288#> <#28289#><#28289#><#28290#>-;SPMgt;<#28290#><#28291#><#28291#> <#28292#>los<#28292#><#65345#><#71328#> <#28293#>(d<#28293#><#28294#>efine<#28294#> <#28295#>(names<#28295#> <#28296#>aloIR)<#28296#> <#28297#>(c<#28297#><#28298#>ond<#28298#> <#28299#>[<#28299#><#28300#>(empty?<#28300#> <#28301#>aloIR)<#28301#> <#28302#>empty]<#28302#> <#28303#>[<#28303#><#28304#>e<#28304#><#28305#>lse<#28305#> <#28306#>(c<#28306#><#28307#>ons<#28307#> <#28308#>(<#28308#>The two functions apply a function to each item in a list. They differ in only one aspect: what they apply to each item on the list. The two boxes emphasize the difference. Each contains a functional value, so we can abstract.#tex2html_wrap73322# <#28310#>(first<#28310#> <#28311#>aloIR))<#28311#> <#28312#>(names<#28312#> <#28313#>(rest<#28313#> <#28314#>aloIR)))]<#28314#><#28315#>))<#28315#>
<#28323#>(d<#28323#><#28324#>efine<#28324#> <#28325#>(convertCF<#28325#> <#28326#>f<#28326#> <#28327#>alon)<#28327#> <#28328#>(c<#28328#><#28329#>ond<#28329#> <#28330#>[<#28330#><#28331#>(empty?<#28331#> <#28332#>alon)<#28332#> <#28333#>empty]<#28333#> <#28334#>[<#28334#><#28335#>e<#28335#><#28336#>lse<#28336#> <#28337#>(c<#28337#><#28338#>ons<#28338#> <#28339#>(<#28339#>#tex2html_wrap73324# <#28341#>(first<#28341#> <#28342#>alon))<#28342#> <#28343#>(convertCF<#28343#> <#28344#>f<#28344#> <#28345#>(rest<#28345#> <#28346#>alon)))]<#28346#><#28347#>))<#28347#>
<#28353#>(d<#28353#><#28354#>efine<#28354#> <#28355#>(names<#28355#> <#28356#>f<#28356#> <#28357#>aloIR)<#28357#> <#28358#>(c<#28358#><#28359#>ond<#28359#> <#28360#>[<#28360#><#28361#>(empty?<#28361#> <#28362#>aloIR)<#28362#> <#28363#>empty]<#28363#> <#28364#>[<#28364#><#28365#>e<#28365#><#28366#>lse<#28366#> <#28367#>(c<#28367#><#28368#>ons<#28368#> <#28369#>(<#28369#>We have replaced the boxed names with <#65349#><#28381#>f<#28381#><#65349#> and added <#65350#><#28382#>f<#28382#><#65350#> as a parameter. Now we replace <#65351#><#28383#>convertCF<#28383#><#65351#> and <#65352#><#28384#>names<#28384#><#65352#> with a new name and thus obtain the abstract function:#tex2html_wrap73326# <#28371#>(first<#28371#> <#28372#>aloIR))<#28372#> <#28373#>(names<#28373#> <#28374#>f<#28374#> <#28375#>(rest<#28375#> <#28376#>aloIR)))]<#28376#><#28377#>))<#28377#>
<#28389#>(d<#28389#><#28390#>efine<#28390#> <#28391#>(map<#28391#> <#28392#>f<#28392#> <#28393#>lon)<#28393#> <#28394#>(c<#28394#><#28395#>ond<#28395#> <#28396#>[<#28396#><#28397#>(empty?<#28397#> <#28398#>lon)<#28398#> <#28399#>empty]<#28399#> <#28400#>[<#28400#><#28401#>else<#28401#> <#28402#>(c<#28402#><#28403#>ons<#28403#> <#28404#>(f<#28404#> <#28405#>(first<#28405#> <#28406#>lon))<#28406#> <#28407#>(map<#28407#> <#28408#>f<#28408#> <#28409#>(rest<#28409#> <#28410#>lon)))]<#28410#><#28411#>))<#28411#>We use the name <#65353#><#28415#>map<#28415#><#65353#> for the result in our running example, because it is the traditional name in programming languages for this specific function.
<#28424#>(d<#28424#><#28425#>efine<#28425#> <#28426#>(f-from-abstract<#28426#> <#28427#>x)<#28427#> <#28428#>(f-abstract<#28428#> <#28429#>boxed-value<#28429#> <#28430#>x))<#28430#>For every proper value <#65358#><#28434#>V<#28434#><#65358#>, <#65359#><#28435#>(f-from-abstract<#28435#>\ <#28436#>V)<#28436#><#65359#> now produces the same answer as <#65360#><#28437#>(f-original<#28437#>\ <#28438#>V)<#28438#><#65360#>. Let us return to our example. Here are the two new definitions:
<#71329#>;; <#65361#><#28443#>convertCF-from-map<#28443#> <#28444#>:<#28444#> <#28445#>lon<#28445#> <#28446#><#28446#><#28447#>-;SPMgt;<#28447#><#28448#><#28448#> <#28449#>lon<#28449#><#65361#><#71329#> <#28450#>(d<#28450#><#28451#>efine<#28451#> <#28452#>(convertCF-from-map<#28452#> <#28453#>alon)<#28453#> <#28454#>(map<#28454#> <#28455#>C<#28455#><#65362#><#28456#><#28456#><#28457#>-;SPMgt;<#28457#><#28458#><#28458#><#65362#><#28459#>F<#28459#> <#28460#>alon))<#28460#>
<#71330#>;; <#65363#><#28466#>names-from-map<#28466#> <#28467#>:<#28467#> <#28468#>loIR<#28468#> <#28469#><#28469#><#28470#>-;SPMgt;<#28470#><#28471#><#28471#> <#28472#>los<#28472#><#65363#><#71330#> <#28473#>(d<#28473#><#28474#>efine<#28474#> <#28475#>(names-from-map<#28475#> <#28476#>aloIR)<#28476#> <#28477#>(map<#28477#> <#28478#>IR-name<#28478#> <#28479#>aloIR))<#28479#>To ensure that these two definitions are equivalent to the old one and, indirectly, that <#65364#><#28483#>map<#28483#><#65364#> is a correct abstraction, we now apply these two functions to the examples that we specified for the development of <#65365#><#28484#>convertCF<#28484#><#65365#> and <#65366#><#28485#>names<#28485#><#65366#>.
<#71331#>;; <#65370#><#28493#>map<#28493#> <#28494#>:<#28494#> <#28495#>(number<#28495#> <#28496#><#28496#><#28497#>-;SPMgt;<#28497#><#28498#><#28498#> <#28499#>number)<#28499#> <#28500#>(listof<#28500#> <#28501#>number)<#28501#> <#28502#><#28502#><#28503#>-;SPMgt;<#28503#><#28504#><#28504#> <#28505#>(listof<#28505#> <#28506#>number)<#28506#><#65370#><#71331#>On the other hand, if we view <#65371#><#28510#>map<#28510#><#65371#> as an abstraction of <#65372#><#28511#>names<#28511#><#65372#>, the contract could be construed as
<#71332#>;; <#65373#><#28516#>map<#28516#> <#28517#>:<#28517#> <#28518#>(IR<#28518#> <#28519#><#28519#><#28520#>-;SPMgt;<#28520#><#28521#><#28521#> <#28522#>symbol)<#28522#> <#28523#>(listof<#28523#> <#28524#>IR)<#28524#> <#28525#><#28525#><#28526#>-;SPMgt;<#28526#><#28527#><#28527#> <#28528#>(listof<#28528#> <#28529#>symbol)<#28529#><#65373#><#71332#>But the first contract would be useless in the second case, and <#28533#>vice versa<#28533#>. To accommodate both cases, we must understand what <#65374#><#28534#>map<#28534#><#65374#> does and then fix a contract. By looking at the definition, we can see that map applies its first argument, a function, to every item on the second argument, a list. This implies that the function must consume the class of data that the list contains. That is, we know <#65375#><#28535#>f<#28535#><#65375#> has the contract
<#71333#>;; <#65376#><#28540#>f<#28540#> <#28541#>:<#28541#> <#28542#>X<#28542#> <#28543#><#28543#><#28544#>-;SPMgt;<#28544#><#28545#><#28545#> <#28546#>?<#28546#><#28547#>?<#28547#><#28548#>?<#28548#><#65376#><#71333#>if <#65377#><#28552#>lon<#28552#><#65377#> contains <#65378#><#28553#>X<#28553#><#65378#>s. Furthermore, <#65379#><#28554#>map<#28554#><#65379#> creates a list from the results of applying <#65380#><#28555#>f<#28555#><#65380#> to each item. Thus, if <#65381#><#28556#>f<#28556#><#65381#> produces <#65382#><#28557#>Y<#28557#><#65382#>s, then <#65383#><#28558#>map<#28558#><#65383#> produces a list of <#65384#><#28559#>Y<#28559#><#65384#>s. Translated into our language of contracts we get this:
<#71334#>;; <#65385#><#28564#>map<#28564#> <#28565#>:<#28565#> <#28566#>(X<#28566#> <#28567#><#28567#><#28568#>-;SPMgt;<#28568#><#28569#><#28569#> <#28570#>Y)<#28570#> <#28571#>(listof<#28571#> <#28572#>X)<#28572#> <#28573#><#28573#><#28574#>-;SPMgt;<#28574#><#28575#><#28575#> <#28576#>(listof<#28576#> <#28577#>Y)<#28577#><#65385#><#71334#>This contract says that <#65386#><#28581#>map<#28581#><#65386#> can produce a list of <#65387#><#28582#>Y<#28582#><#65387#>s from a list of <#65388#><#28583#>X<#28583#><#65388#>s and a function from <#65389#><#28584#>X<#28584#><#65389#> to <#65390#><#28585#>Y<#28585#><#65390#>---no matter for what collection of <#65391#><#28586#>X<#28586#><#65391#> and <#65392#><#28587#>Y<#28587#><#65392#> stand.
<#71335#>;; <#65395#><#28599#>tabulate-sin<#28599#> <#28600#>:<#28600#> <#28601#>number<#28601#> <#28602#><#28602#><#28603#>-;SPMgt;<#28603#><#28604#><#28604#> <#28605#>lon<#28605#><#65395#><#71335#> <#71336#>;; to tabulate <#65396#><#28606#>sin<#28606#><#65396#> between <#65397#><#28607#>n<#28607#><#65397#> <#71336#> <#71337#>;; and <#65398#><#28608#>0<#28608#><#65398#> (inclusive) in a list<#71337#> <#28609#>(d<#28609#><#28610#>efine<#28610#> <#28611#>(tabulate-sin<#28611#> <#28612#>n)<#28612#> <#28613#>(c<#28613#><#28614#>ond<#28614#> <#28615#>[<#28615#><#28616#>(=<#28616#> <#28617#>n<#28617#> <#28618#>0)<#28618#> <#28619#>(list<#28619#> <#28620#>(sin<#28620#> <#28621#>0))]<#28621#> <#28622#>[<#28622#><#28623#>e<#28623#><#28624#>lse<#28624#> <#28625#>(c<#28625#><#28626#>ons<#28626#> <#28627#>(sin<#28627#> <#28628#>n)<#28628#> <#28629#>(tabulate-sin<#28629#> <#28630#>(sub1<#28630#> <#28631#>n)))]<#28631#><#28632#>))<#28632#>
<#71338#>;; <#65399#><#28638#>tabulate-sqrt<#28638#> <#28639#>:<#28639#> <#28640#>number<#28640#> <#28641#><#28641#><#28642#>-;SPMgt;<#28642#><#28643#><#28643#> <#28644#>lon<#28644#><#65399#><#71338#> <#71339#>;; to tabulate <#65400#><#28645#>sqrt<#28645#><#65400#> between <#65401#><#28646#>n<#28646#><#65401#> <#71339#> <#71340#>;; and <#65402#><#28647#>0<#28647#><#65402#> (inclusive) in a list<#71340#> <#28648#>(d<#28648#><#28649#>efine<#28649#> <#28650#>(tabulate-sqrt<#28650#> <#28651#>n)<#28651#> <#28652#>(c<#28652#><#28653#>ond<#28653#> <#28654#>[<#28654#><#28655#>(=<#28655#> <#28656#>n<#28656#> <#28657#>0)<#28657#> <#28658#>(list<#28658#> <#28659#>(sqrt<#28659#> <#28660#>0))]<#28660#> <#28661#>[<#28661#><#28662#>e<#28662#><#28663#>lse<#28663#> <#28664#>(c<#28664#><#28665#>ons<#28665#> <#28666#>(sqrt<#28666#> <#28667#>n)<#28667#> <#28668#>(tabulate-sqrt<#28668#> <#28669#>(sub1<#28669#> <#28670#>n)))]<#28670#><#28671#>))<#28671#>Make sure to define the two functions in terms of <#65403#><#28675#>tabulate<#28675#><#65403#>. Also use <#65404#><#28676#>tabulate<#28676#><#65404#> to define a tabulation function for <#65405#><#28677#>square<#28677#><#65405#> and <#65406#><#28678#>tan<#28678#><#65406#>. What would be a good, general contract?~ Solution<#65407#><#65407#> <#28684#>Exercise 21.1.2<#28684#>
<#71341#>;; <#65409#><#28691#>sum<#28691#> <#28692#>:<#28692#> <#28693#>(listof<#28693#> <#28694#>number)<#28694#> <#28695#><#28695#><#28696#>-;SPMgt;<#28696#><#28697#><#28697#> <#28698#>number<#28698#><#65409#><#71341#> <#28699#>;; to compute the sum of <#28699#> <#71342#>;; the numbers on <#65410#><#28700#>alon<#28700#><#65410#><#71342#> <#28701#>(d<#28701#><#28702#>efine<#28702#> <#28703#>(sum<#28703#> <#28704#>alon)<#28704#> <#28705#>(c<#28705#><#28706#>ond<#28706#> <#28707#>[<#28707#><#28708#>(empty?<#28708#> <#28709#>alon)<#28709#> <#28710#>0]<#28710#> <#28711#>[<#28711#><#28712#>else<#28712#> <#28713#>(+<#28713#> <#28714#>(first<#28714#> <#28715#>alon)<#28715#> <#28716#>(sum<#28716#> <#28717#>(rest<#28717#> <#28718#>alon)))]<#28718#><#28719#>))<#28719#>
<#71343#>;; <#65411#><#28725#>product<#28725#> <#28726#>:<#28726#> <#28727#>(listof<#28727#> <#28728#>number)<#28728#> <#28729#><#28729#><#28730#>-;SPMgt;<#28730#><#28731#><#28731#> <#28732#>number<#28732#><#65411#><#71343#> <#28733#>;; to compute the product of <#28733#> <#71344#>;; the numbers on <#65412#><#28734#>alon<#28734#><#65412#><#71344#> <#28735#>(d<#28735#><#28736#>efine<#28736#> <#28737#>(product<#28737#> <#28738#>alon)<#28738#> <#28739#>(c<#28739#><#28740#>ond<#28740#> <#28741#>[<#28741#><#28742#>(empty?<#28742#> <#28743#>alon)<#28743#> <#28744#>1]<#28744#> <#28745#>[<#28745#><#28746#>else<#28746#> <#28747#>(*<#28747#> <#28748#>(first<#28748#> <#28749#>alon)<#28749#> <#28750#>(product<#28750#> <#28751#>(rest<#28751#> <#28752#>alon)))]<#28752#><#28753#>))<#28753#>Don't forget to test <#65413#><#28757#>fold<#28757#><#65413#>. After <#65414#><#28758#>fold<#28758#><#65414#> is defined and tested, use it to define <#65415#><#28759#>append<#28759#><#65415#>, which juxtaposes the items of two lists or, equivalently, replaces <#65416#><#28760#>empty<#28760#><#65416#> in the first list with the second list:
<#28765#>(append<#28765#> <#28766#>(list<#28766#> <#28767#>1<#28767#> <#28768#>2<#28768#> <#28769#>3)<#28769#> <#28770#>(list<#28770#> <#28771#>4<#28771#> <#28772#>5<#28772#> <#28773#>6<#28773#> <#28774#>7<#28774#> <#28775#>8))<#28775#> <#28776#>=<#28776#> <#28777#>(list<#28777#> <#28778#>1<#28778#> <#28779#>2<#28779#> <#28780#>3<#28780#> <#28781#>4<#28781#> <#28782#>5<#28782#> <#28783#>6<#28783#> <#28784#>7<#28784#> <#28785#>8)<#28785#>Finally, define <#65417#><#28789#>map<#28789#><#65417#> using <#65418#><#28790#>fold<#28790#><#65418#>. Compare the four examples to formulate a contract.~ Solution<#65419#><#65419#> <#28796#>Exercise 21.1.3<#28796#>
<#71345#>;; <#65421#><#28803#>copy<#28803#> <#28804#>:<#28804#> <#28805#>N<#28805#> <#28806#>X<#28806#> <#28807#><#28807#><#28808#>-;SPMgt;<#28808#><#28809#><#28809#> <#28810#>(listof<#28810#> <#28811#>X)<#28811#><#65421#><#71345#> <#28812#>;; to create a list that contains<#28812#> <#71346#>;; <#65422#><#28813#>obj<#28813#><#65422#> <#65423#><#28814#>n<#28814#><#65423#> times<#71346#> <#28815#>(d<#28815#><#28816#>efine<#28816#> <#28817#>(copy<#28817#> <#28818#>n<#28818#> <#28819#>obj)<#28819#> <#28820#>(c<#28820#><#28821#>ond<#28821#> <#28822#>[<#28822#><#28823#>(zero?<#28823#> <#28824#>n)<#28824#> <#28825#>empty]<#28825#> <#28826#>[<#28826#><#28827#>else<#28827#> <#28828#>(cons<#28828#> <#28829#>obj<#28829#> <#28830#>(copy<#28830#> <#28831#>(sub1<#28831#> <#28832#>n)<#28832#> <#28833#>obj))]<#28833#><#28834#>))<#28834#>~
<#71347#>;; <#65424#><#28840#>n-adder<#28840#> <#28841#>:<#28841#> <#28842#>N<#28842#> <#28843#>number<#28843#> <#28844#><#28844#><#28845#>-;SPMgt;<#28845#><#28846#><#28846#> <#28847#>number<#28847#><#65424#><#71347#> <#71348#>;; to add <#65425#><#28848#>n<#28848#><#65425#> to <#65426#><#28849#>x<#28849#><#65426#> using<#71348#> <#71349#>;; <#65427#><#28850#>(+<#28850#> <#28851#>1<#28851#> <#28852#>...)<#28852#><#65427#> only<#71349#> <#28853#>(d<#28853#><#28854#>efine<#28854#> <#28855#>(n-adder<#28855#> <#28856#>n<#28856#> <#28857#>x)<#28857#> <#28858#>(c<#28858#><#28859#>ond<#28859#> <#28860#>[<#28860#><#28861#>(zero?<#28861#> <#28862#>n)<#28862#> <#28863#>x]<#28863#> <#28864#>[<#28864#><#28865#>else<#28865#> <#28866#>(+<#28866#> <#28867#>1<#28867#> <#28868#>(n-adder<#28868#> <#28869#>(sub1<#28869#> <#28870#>n)<#28870#> <#28871#>x))]<#28871#><#28872#>))<#28872#>Don't forget to test <#65428#><#28876#>natural-n<#28876#><#65428#>. Also use <#65429#><#28877#>natural-n<#28877#><#65429#> to define <#65430#><#28878#>n-multiplier<#28878#><#65430#>, which consumes <#65431#><#28879#>n<#28879#><#65431#> and <#65432#><#28880#>x<#28880#><#65432#> and produces <#65433#><#28881#>n<#28881#><#65433#> times <#65434#><#28882#>x<#28882#><#65434#> with additions only. Use the examples to formulate a contract. <#28883#>Hint:<#28883#> \ The two function differ more than, say, the functions <#65435#><#28884#>sum<#28884#><#65435#> and <#65436#><#28885#>product<#28885#><#65436#> in exercise~#exabssumprod#28886>
<#28894#>Formulating General Contracts<#28894#>:\ To increase the usefulness of an
abstract function, we must formulate a contract that describes its
applicability in the most general terms possible. In principle, abstracting
contracts follows the same recipe that we use for abstracting functions. We
compare and contrast the old contracts; then we replace the differences by
variables. But the process is complicated and requires a lot of practice.
Let us start with our running example: <#65438#><#28895#>convertCF<#28895#><#65438#> and <#65439#><#28896#>names<#28896#><#65439#>: