Note: Designing Abstractions from Templates

At the very beginning of this part of the book, we discussed how we design sets of functions from the same template. More specifically, when we design a set of functions that all consume the same kind of data, we reuse the same template over and over again. It is therefore not surprising that the function definitions look similar and that we will abstract them later. Indeed, we could abstract from the templates directly. While this topic is highly advanced and still subject of research in the area of programming languages, we can discuss it with a short example. Consider the template for lists:
<#29457#>(d<#29457#><#29458#>efine<#29458#> <#29459#>(fun-for-l<#29459#> <#29460#>l)<#29460#>
  <#29461#>(c<#29461#><#29462#>ond<#29462#> 
    <#29463#>[<#29463#><#29464#>(empty?<#29464#> <#29465#>l)<#29465#> <#29466#>...]<#29466#> 
    <#29467#>[<#29467#><#29468#>else<#29468#> <#29469#>...<#29469#> <#29470#>(first<#29470#> <#29471#>l)<#29471#> <#29472#>...<#29472#> <#29473#>(fun-for-l<#29473#> <#29474#>(rest<#29474#> <#29475#>l))<#29475#> <#29476#>...]<#29476#><#29477#>))<#29477#> 
It contains two gaps, one in each clause. When we define a list-processing functions, we fill these gaps. In the first clause, we typically place a plain value. For the second one, we combine <#65559#><#29481#>(first<#29481#>\ <#29482#>l)<#29482#><#65559#> and <#65560#><#29483#>(f<#29483#>\ <#29484#>(rest<#29484#>\ <#29485#>l))<#29485#><#65560#> where <#65561#><#29486#>f<#29486#><#65561#> is the recursive function. We can abstract over this programming task with the following function:
<#71372#>;; <#65562#><#29491#>reduce<#29491#> <#29492#>:<#29492#> <#29493#>X<#29493#> <#29494#>(X<#29494#> <#29495#>Y<#29495#> <#29496#><#29496#><#29497#>-;SPMgt;<#29497#><#29498#><#29498#> <#29499#>Y)<#29499#> <#29500#>(listof<#29500#> <#29501#>Y)<#29501#> <#29502#><#29502#><#29503#>-;SPMgt;<#29503#><#29504#><#29504#> <#29505#>Y<#29505#><#65562#><#71372#>
<#29506#>(d<#29506#><#29507#>efine<#29507#> <#29508#>(reduce<#29508#> <#29509#>base<#29509#> <#29510#>combine<#29510#> <#29511#>l)<#29511#> 
  <#29512#>(c<#29512#><#29513#>ond<#29513#> 
    <#29514#>[<#29514#><#29515#>(empty?<#29515#> <#29516#>l)<#29516#> <#29517#>base]<#29517#> 
    <#29518#>[<#29518#><#29519#>else<#29519#> <#29520#>(c<#29520#><#29521#>ombine<#29521#> <#29522#>(first<#29522#> <#29523#>l)<#29523#> 
            <#29524#>(reduce<#29524#> <#29525#>base<#29525#> <#29526#>combine<#29526#> <#29527#>(rest<#29527#> <#29528#>l)))]<#29528#><#29529#>))<#29529#> 
It consumes two extra arguments: <#65563#><#29533#>base<#29533#><#65563#>, which is the value for the base case, and <#65564#><#29534#>combine<#29534#><#65564#>, which is a function that performs the value combination for the second clause. Using <#65565#><#29535#>reduce<#29535#><#65565#> we can define many plain list-processing functions as well as almost all the functions of figure~#figschemeholist#29536>. Here are two of them:
<#71373#>;; <#65566#><#29541#>sum<#29541#> <#29542#>:<#29542#> <#29543#>(listof<#29543#> <#29544#>number)<#29544#> <#29545#><#29545#><#29546#>-;SPMgt;<#29546#><#29547#><#29547#> <#29548#>number<#29548#><#65566#><#71373#>
<#29549#>(define<#29549#> <#29550#>(sum<#29550#> <#29551#>l)<#29551#> <#29552#>(reduce<#29552#> <#29553#>0<#29553#> <#29554#>+<#29554#> <#29555#>l))<#29555#> 
<#71374#>;; <#65567#><#29561#>product<#29561#> <#29562#>:<#29562#> <#29563#>(listof<#29563#> <#29564#>number)<#29564#> <#29565#><#29565#><#29566#>-;SPMgt;<#29566#><#29567#><#29567#> <#29568#>number<#29568#><#65567#><#71374#>
<#29569#>(define<#29569#> <#29570#>(product<#29570#> <#29571#>l)<#29571#> <#29572#>(reduce<#29572#> <#29573#>1<#29573#> <#29574#>*<#29574#> <#29575#>l))<#29575#> 
For <#65568#><#29579#>sum<#29579#><#65568#>, the base case always produces <#65569#><#29580#>0<#29580#><#65569#>; adding the first item and the result of the natural recursion combines the values of the second clause. Analogous reasoning explains <#65570#><#29581#>product<#29581#><#65570#>. To define <#65571#><#29582#>sort<#29582#><#65571#>, we need to define an auxiliary function first:
<#71375#>;; <#65572#><#29587#>sort<#29587#> <#29588#>:<#29588#> <#29589#>(listof<#29589#> <#29590#>number)<#29590#> <#29591#><#29591#><#29592#>-;SPMgt;<#29592#><#29593#><#29593#> <#29594#>(listof<#29594#> <#29595#>number)<#29595#><#65572#><#71375#>
<#29596#>(d<#29596#><#29597#>efine<#29597#> <#29598#>sort<#29598#> 
  <#29599#>(l<#29599#><#29600#>ocal<#29600#> <#29601#>((d<#29601#><#29602#>efine<#29602#> <#29603#>(insert<#29603#> <#29604#>an<#29604#> <#29605#>alon)<#29605#> 
            <#29606#>(c<#29606#><#29607#>ond<#29607#> 
              <#29608#>[<#29608#><#29609#>(empty?<#29609#> <#29610#>alon)<#29610#> <#29611#>(list<#29611#> <#29612#>an)]<#29612#> 
              <#29613#>[<#29613#><#29614#>else<#29614#> <#29615#>(c<#29615#><#29616#>ond<#29616#> 
                      <#29617#>[<#29617#><#29618#>(;SPMgt;<#29618#> <#29619#>an<#29619#> <#29620#>(first<#29620#> <#29621#>alon))<#29621#> <#29622#>(cons<#29622#> <#29623#>an<#29623#> <#29624#>alon)]<#29624#> 
                      <#29625#>[<#29625#><#29626#>else<#29626#> <#29627#>(cons<#29627#> <#29628#>(first<#29628#> <#29629#>alon)<#29629#> <#29630#>(insert<#29630#> <#29631#>an<#29631#> <#29632#>(rest<#29632#> <#29633#>alon)))]<#29633#><#29634#>)]<#29634#><#29635#>)))<#29635#> 
    <#29636#>(reduce<#29636#> <#29637#>empty<#29637#> <#29638#>insert)))<#29638#> 
Other list-processing functions can be defined in a similar manner.