The combination of <#65619#><#29839#>local<#29839#>-expression<#65619#>s and functions-as-values
simplifies our recipe for creating abstract functions. Consider our very
first example in figure~#figcmpabovebelow#29840> again. If we replace the
contents of the boxes with <#65620#><#29841#>rel-op<#29841#><#65620#>, we get a function that has a
free variable. To avoid this, we can either add <#65621#><#29842#>rel-op<#29842#><#65621#> to the
parameters or we can wrap the definition in a <#65622#><#29843#>local<#29843#><#65622#> and prefix it
with a function that consumes <#65623#><#29844#>rel-op<#29844#><#65623#>:
<#29849#>(d<#29849#><#29850#>efine<#29850#> <#29851#>(filter2<#29851#> <#29852#>rel-op)<#29852#>
<#29853#>(l<#29853#><#29854#>ocal<#29854#> <#29855#>((d<#29855#><#29856#>efine<#29856#> <#29857#>(abs-fun<#29857#> <#29858#>alon<#29858#> <#29859#>t)<#29859#>
<#29860#>(c<#29860#><#29861#>ond<#29861#>
<#29862#>[<#29862#><#29863#>(empty?<#29863#> <#29864#>alon)<#29864#> <#29865#>empty]<#29865#>
<#29866#>[<#29866#><#29867#>e<#29867#><#29868#>lse<#29868#>
<#29869#>(c<#29869#><#29870#>ond<#29870#>
<#29871#>[<#29871#><#29872#>(<#29872#>#tex2html_wrap73330# <#29874#>(first<#29874#> <#29875#>alon)<#29875#> <#29876#>t)<#29876#>
<#29877#>(c<#29877#><#29878#>ons<#29878#> <#29879#>(first<#29879#> <#29880#>alon)<#29880#>
<#29881#>(abs-fun<#29881#> <#29882#>(rest<#29882#> <#29883#>alon)<#29883#> <#29884#>t))]<#29884#>
<#29885#>[<#29885#><#29886#>el<#29886#><#29887#>se<#29887#>
<#29888#>(abs-fun<#29888#> <#29889#>(rest<#29889#> <#29890#>alon)<#29890#> <#29891#>t)]<#29891#><#29892#>)]<#29892#><#29893#>)))<#29893#>
<#29894#>abs-fun))<#29894#>
If we also make the <#65625#><#29898#>local<#29898#><#65625#>ly defined function the result of the
function, we have defined an abstraction of the two original functions.
Put differently, we follow the example of <#65626#><#29899#>add<#29899#><#65626#> in the preceding
section. Like <#65627#><#29900#>add<#29900#><#65627#>, <#65628#><#29901#>filter2<#29901#><#65628#> consumes an argument, defines
a function, and returns this function as a result. The result remembers
the <#65629#><#29902#>rel-op<#29902#><#65629#> argument for good as the following evaluation shows:
<#29907#>(filter2<#29907#> <#29908#>;SPMlt;)<#29908#>
<#29916#>=<#29916#> <#29917#>(l<#29917#><#29918#>ocal<#29918#> <#29919#>((d<#29919#><#29920#>efine<#29920#> <#29921#>(abs-fun<#29921#> <#29922#>alon<#29922#> <#29923#>t)<#29923#>
<#29924#>(c<#29924#><#29925#>ond<#29925#>
<#29926#>[<#29926#><#29927#>(empty?<#29927#> <#29928#>alon)<#29928#> <#29929#>empty]<#29929#>
<#29930#>[<#29930#><#29931#>e<#29931#><#29932#>lse<#29932#>
<#29933#>(c<#29933#><#29934#>ond<#29934#>
<#29935#>[<#29935#><#29936#>(;SPMlt;<#29936#> <#29937#>(first<#29937#> <#29938#>alon)<#29938#> <#29939#>t)<#29939#>
<#29940#>(c<#29940#><#29941#>ons<#29941#> <#29942#>(first<#29942#> <#29943#>alon)<#29943#>
<#29944#>(abs-fun<#29944#> <#29945#>(rest<#29945#> <#29946#>alon)<#29946#> <#29947#>t))]<#29947#>
<#29948#>[<#29948#><#29949#>el<#29949#><#29950#>se<#29950#>
<#29951#>(abs-fun<#29951#> <#29952#>(rest<#29952#> <#29953#>alon)<#29953#> <#29954#>t)]<#29954#><#29955#>)]<#29955#><#29956#>)))<#29956#>
<#29957#>abs-fun)<#29957#>
<#29965#>=<#29965#> <#29966#>(<#29966#><#29967#>d<#29967#><#29968#>efine<#29968#> <#29969#>(below3<#29969#> <#29970#>alon<#29970#> <#29971#>t)<#29971#>
<#29972#>(c<#29972#><#29973#>ond<#29973#>
<#29974#>[<#29974#><#29975#>(empty?<#29975#> <#29976#>alon)<#29976#> <#29977#>empty]<#29977#>
<#29978#>[<#29978#><#29979#>e<#29979#><#29980#>lse<#29980#>
<#29981#>(c<#29981#><#29982#>ond<#29982#>
<#29983#>[<#29983#><#29984#>(;SPMlt;<#29984#> <#29985#>(first<#29985#> <#29986#>alon)<#29986#> <#29987#>t)<#29987#>
<#29988#>(c<#29988#><#29989#>ons<#29989#> <#29990#>(first<#29990#> <#29991#>alon)<#29991#>
<#29992#>(below3<#29992#> <#29993#>(rest<#29993#> <#29994#>alon)<#29994#> <#29995#>t))]<#29995#>
<#29996#>[<#29996#><#29997#>e<#29997#><#29998#>lse<#29998#>
<#29999#>(below3<#29999#> <#30000#>(rest<#30000#> <#30001#>alon)<#30001#> <#30002#>t)]<#30002#><#30003#>)]<#30003#><#30004#>))<#30004#>
<#30005#>below3<#30005#>
Remember that as we lift a <#65630#><#30009#>local<#30009#><#65630#> definition to the top-level
definitions, we also rename the function in case the same <#65631#><#30010#>local<#30010#><#65631#> is
evaluated again. Here we choose the name <#65632#><#30011#>below3<#30011#><#65632#> to indicate what
the function does. And indeed, a comparison between <#65633#><#30012#>below<#30012#><#65633#> and
<#65634#><#30013#>below3<#30013#><#65634#> reveals that the only difference is the name of the
function.
From the calculation, it follows that we can give the result of
<#65635#><#30014#>(filter2<#30014#>\ <#30015#>;SPMlt;)<#30015#><#65635#> a name and use it as if it were <#65636#><#30016#>below<#30016#><#65636#>. More
succinctly,
<#30021#>(define<#30021#> <#30022#>below2<#30022#> <#30023#>(filter2<#30023#> <#30024#>;SPMlt;))<#30024#>
is equivalent to
<#30032#>(def<#30032#><#30033#>ine<#30033#> <#30034#>(below3<#30034#> <#30035#>alon<#30035#> <#30036#>t)<#30036#>
<#30037#>(c<#30037#><#30038#>ond<#30038#>
<#30039#>[<#30039#><#30040#>(empty?<#30040#> <#30041#>alon)<#30041#> <#30042#>empty]<#30042#>
<#30043#>[<#30043#><#30044#>e<#30044#><#30045#>lse<#30045#>
<#30046#>(c<#30046#><#30047#>ond<#30047#>
<#30048#>[<#30048#><#30049#>(;SPMlt;<#30049#> <#30050#>(first<#30050#> <#30051#>alon)<#30051#> <#30052#>t)<#30052#>
<#30053#>(c<#30053#><#30054#>ons<#30054#> <#30055#>(first<#30055#> <#30056#>alon)<#30056#>
<#30057#>(below3<#30057#> <#30058#>(rest<#30058#> <#30059#>alon)<#30059#> <#30060#>t))]<#30060#>
<#30061#>[<#30061#><#30062#>e<#30062#><#30063#>lse<#30063#>
<#30064#>(below3<#30064#> <#30065#>(rest<#30065#> <#30066#>alon)<#30066#> <#30067#>t)]<#30067#><#30068#>)]<#30068#><#30069#>))<#30069#>
<#30070#>(define<#30070#> <#30071#>below2<#30071#> <#30072#>below3)<#30072#>
which means <#65637#><#30076#>below2<#30076#><#65637#> is just another name for <#65638#><#30077#>below3<#30077#><#65638#> and
which directly proves that our abstract function correctly implements <#65639#><#30078#>below<#30078#><#65639#>.
The example suggests a variant of the abstraction recipe from
section~#secdesignabstract#30079>:
- The comparison:
- The new recipe still requires us to compare and to
mark the differences.
- The abstraction:
- The new step concerns the way we define the
abstract function. We place one of the functions into a
<#65640#><#30081#>local<#30081#>-expression<#65640#> and use the name of the function as the body of
the <#65641#><#30082#>local<#30082#><#65641#>:
<#30087#>(l<#30087#><#30088#>ocal<#30088#> <#30089#>((d<#30089#><#30090#>efine<#30090#> <#30091#>(concrete-fun<#30091#> <#30092#>x<#30092#> <#30093#>y<#30093#> <#30094#>z)<#30094#>
<#30095#>...<#30095#> #tex2html_wrap73332# <#30097#>...<#30097#> #tex2html_wrap73334# <#30099#>...))<#30099#>
<#30100#>concrete-fun)<#30100#>
From that, we can create the abstract function by listing the names in the
boxes as parameters:
<#30108#>(d<#30108#><#30109#>efine<#30109#> <#30110#>(abs-fun<#30110#> <#30111#>op1<#30111#> <#30112#>op2)<#30112#>
<#30113#>(l<#30113#><#30114#>ocal<#30114#> <#30115#>((d<#30115#><#30116#>efine<#30116#> <#30117#>(concrete-fun<#30117#> <#30118#>x<#30118#> <#30119#>y<#30119#> <#30120#>z)<#30120#>
<#30121#>...<#30121#> #tex2html_wrap73336# <#30123#>...<#30123#> #tex2html_wrap73338# <#30125#>...))<#30125#>
<#30126#>concrete-fun))<#30126#>
If <#65646#><#30130#>op1<#30130#><#65646#> or <#65647#><#30131#>op2<#30131#><#65647#> is a special symbol, say <#65648#><#30132#>;SPMlt;<#30132#><#65648#>, we
rename it into something that is more meaningful in the new context.
- The test:
- To test the abstract function, we define the concrete
functions again, as before. Consider the example of <#65649#><#30133#>below<#30133#><#65649#> and
<#65650#><#30134#>above<#30134#><#65650#>. Obtaining <#65651#><#30135#>below<#30135#><#65651#> and <#65652#><#30136#>above<#30136#><#65652#> as instances of
<#65653#><#30137#>filter2<#30137#><#65653#> is now straightforward:
<#30142#>(define<#30142#> <#30143#>below2<#30143#> <#30144#>(filter2<#30144#> <#30145#>;SPMlt;))<#30145#>
<#30146#>(define<#30146#> <#30147#>above2<#30147#> <#30148#>(filter2<#30148#> <#30149#>;SPMgt;))<#30149#>
We simply apply <#65654#><#30153#>filter2<#30153#><#65654#> to the contents of the box in the
respective concrete function and that application produces the old
function.
- The contract:
- The contract of an abstract function contains two
arrows. After all, the function produces a function, and to describe this
relationship the type to the right of the first arrow must contain another
arrow.
Here is the contract for <#65655#><#30154#>filter2<#30154#><#65655#>:
<#71379#>;; <#65656#><#30159#>filter2<#30159#> <#30160#>:<#30160#> <#30161#>(X<#30161#> <#30162#>Y<#30162#> <#30163#><#30163#><#30164#>-;SPMgt;<#30164#><#30165#><#30165#> <#30166#>boolean)<#30166#> <#30167#><#30167#><#30168#>-;SPMgt;<#30168#><#30169#><#30169#> <#30170#>(Y<#30170#> <#30171#>(listof<#30171#> <#30172#>X)<#30172#> <#30173#><#30173#><#30174#>-;SPMgt;<#30174#><#30175#><#30175#> <#30176#>(listof<#30176#> <#30177#>X))<#30177#><#65656#><#71379#>
It consumes a comparison function and produces a concrete filter-style
function.
The generalization of the contract works as before.
Given our experience with the first design recipe, the second one is only a
question of practice.
<#30184#>Exercise 22.2.1<#30184#>
Define an abstraction of the functions <#65657#><#30186#>convertCF<#30186#><#65657#> and
<#65658#><#30187#>names<#30187#><#65658#> from section~#secpostabs#30188> using the new recipe for
abstraction.~ Solution<#65659#><#65659#>
<#30194#>Exercise 22.2.2<#30194#>
Define an abstract version of <#65660#><#30196#>sort<#30196#><#65660#> (see
exercise~#exabssort#30197>) using the new recipe for
abstraction.~ Solution<#65661#><#65661#>
<#30203#>Exercise 22.2.3<#30203#>
Define <#65662#><#30205#>fold<#30205#><#65662#> using the new recipe for abstraction. Recall that
<#65663#><#30206#>fold<#30206#><#65663#> abstracts the following pair of functions:
<#71380#>;; <#65664#><#30211#>sum<#30211#> <#30212#>:<#30212#> <#30213#>(listof<#30213#> <#30214#>number)<#30214#> <#30215#><#30215#><#30216#>-;SPMgt;<#30216#><#30217#><#30217#> <#30218#>number<#30218#><#65664#><#71380#>
<#71381#>;; to compute the sum of <#65665#><#30219#>alon<#30219#><#65665#><#71381#>
<#30220#>(d<#30220#><#30221#>efine<#30221#> <#30222#>(sum<#30222#> <#30223#>alon)<#30223#>
<#30224#>(c<#30224#><#30225#>ond<#30225#>
<#30226#>[<#30226#><#30227#>(empty?<#30227#> <#30228#>alon)<#30228#> <#30229#>0]<#30229#>
<#30230#>[<#30230#><#30231#>else<#30231#> <#30232#>(+<#30232#> <#30233#>(first<#30233#> <#30234#>alon)<#30234#>
<#30235#>(sum<#30235#> <#30236#>(rest<#30236#> <#30237#>alon)))]<#30237#><#30238#>))<#30238#>
<#71382#>;; <#65666#><#30244#>product<#30244#> <#30245#>:<#30245#> <#30246#>(listof<#30246#> <#30247#>number)<#30247#> <#30248#><#30248#><#30249#>-;SPMgt;<#30249#><#30250#><#30250#> <#30251#>number<#30251#><#65666#><#71382#>
<#71383#>;; to compute the product of <#65667#><#30252#>alon<#30252#><#65667#><#71383#>
<#30253#>(d<#30253#><#30254#>efine<#30254#> <#30255#>(product<#30255#> <#30256#>alon)<#30256#>
<#30257#>(c<#30257#><#30258#>ond<#30258#>
<#30259#>[<#30259#><#30260#>(empty?<#30260#> <#30261#>alon)<#30261#> <#30262#>1]<#30262#>
<#30263#>[<#30263#><#30264#>else<#30264#> <#30265#>(*<#30265#> <#30266#>(first<#30266#> <#30267#>alon)<#30267#>
<#30268#>(product<#30268#> <#30269#>(rest<#30269#> <#30270#>alon)))]<#30270#><#30271#>))<#30271#>
Solution<#65668#><#65668#>