A First Useful Example

Let's take a look at the definitions in figure~#figab#44670>. The function <#68114#><#44671#>add-to-address-book<#44671#><#68114#> consumes a symbol and a number. The former represents a name, the latter a phone number. Its body contains a <#68115#><#44672#>set!<#44672#>-expression<#68115#> for <#68116#><#44673#>address-book<#44673#><#68116#>, a variable <#68117#><#44674#>define<#44674#><#68117#>d at top-level variable. The function <#68118#><#44675#>lookup<#44675#><#68118#> consumes an address book and a name; its result is the matching phone number or <#68119#><#44676#>false<#44676#><#68119#>, if the name is not in <#68120#><#44677#>address-book<#44677#><#68120#>.
 
<#44682#>(define<#44682#> <#44683#>address-book<#44683#> <#44684#>empty)<#44684#> 
<#71701#>;; <#68121#><#44685#>add-to-address-book<#44685#> <#44686#>:<#44686#> <#44687#>symbol<#44687#> <#44688#>number<#44688#> <#44689#><#44689#><#44690#>-;SPMgt;<#44690#><#44691#><#44691#> <#44692#>void<#44692#><#68121#><#71701#> 
<#44693#>(d<#44693#><#44694#>efine<#44694#> <#44695#>(add-to-address-book<#44695#> <#44696#>name<#44696#> <#44697#>phone)<#44697#> 
  <#44698#>(set!<#44698#> <#44699#>address-book<#44699#> <#44700#>(cons<#44700#> <#44701#>(list<#44701#> <#44702#>name<#44702#> <#44703#>phone)<#44703#> <#44704#>address-book)))<#44704#> 
<#71702#>;; <#68122#><#44712#>lookup<#44712#> <#44713#>:<#44713#> <#44714#>symbol<#44714#> <#44715#>(listof<#44715#> <#44716#>(list<#44716#> <#44717#>symbol<#44717#> <#44718#>number))<#44718#> <#44719#><#44719#><#44720#>-;SPMgt;<#44720#><#44721#><#44721#> <#44722#>number<#44722#> <#44723#>or<#44723#> <#44724#>false<#44724#><#68122#><#71702#>
<#71703#>;; to lookup the phone number for <#68123#><#44725#>name<#44725#><#68123#> in <#68124#><#44726#>ab<#44726#><#68124#><#71703#> 
<#44727#>(d<#44727#><#44728#>efine<#44728#> <#44729#>(lookup<#44729#> <#44730#>name<#44730#> <#44731#>ab)<#44731#> 
  <#44732#>(c<#44732#><#44733#>ond<#44733#> 
    <#44734#>[<#44734#><#44735#>(empty?<#44735#> <#44736#>ab)<#44736#> <#44737#>false<#44737#><#44738#>]<#44738#> 
    <#44739#>[<#44739#><#44740#>else<#44740#> <#44741#>(c<#44741#><#44742#>ond<#44742#> 
            <#44743#>[<#44743#><#44744#>(symbol=?<#44744#> <#44745#>(first<#44745#> <#44746#>(first<#44746#> <#44747#>ab))<#44747#> <#44748#>name)<#44748#> 
             <#44749#>(second<#44749#> <#44750#>(first<#44750#> <#44751#>ab))]<#44751#> 
            <#44752#>[<#44752#><#44753#>else<#44753#> <#44754#>(lookup<#44754#> <#44755#>name<#44755#> <#44756#>(rest<#44756#> <#44757#>ab))]<#44757#><#44758#>)]<#44758#><#44759#>))<#44759#> 
<#44763#>Figure: The basic address-book program<#44763#>
Using <#68125#><#44765#>lookup<#44765#><#68125#>, we can study the effect of the <#68126#><#44766#>set!<#44766#><#68126#> expression in <#68127#><#44767#>add-to-address-book<#44767#><#68127#>. Supposed we evaluate <#68128#><#44768#>(lookup<#44768#>\ <#44769#>'<#44769#><#44770#>Adam<#44770#>\ <#44771#>address-book)<#44771#><#68128#> with the given definitions:
  <#44776#>(lookup<#44776#> <#44777#>'<#44777#><#44778#>Adam<#44778#> <#44779#>address-book)<#44779#>
<#44780#>=<#44780#> <#44781#>(lookup<#44781#> <#44782#>'<#44782#><#44783#>Adam<#44783#> <#44784#>empty)<#44784#> 
<#44785#>=<#44785#> <#44786#>(c<#44786#><#44787#>ond<#44787#> 
    <#44788#>[<#44788#><#44789#>(empty?<#44789#> <#44790#>empty)<#44790#> <#44791#>false<#44791#><#44792#>]<#44792#> 
    <#44793#>[<#44793#><#44794#>else<#44794#> <#44795#>...]<#44795#><#44796#>)<#44796#> 
<#44797#>=<#44797#> <#44798#>false<#44798#> 
Because <#68129#><#44802#>address-book<#44802#><#68129#> is <#68130#><#44803#>empty<#44803#><#68130#>, we get <#68131#><#44804#>false<#44804#><#68131#>, and the calculation is straightforward. Now let's evaluate the following in the <#44805#>Interactions<#44805#> window:
 
<#44810#>(begin<#44810#> <#44811#>(add-to-address-book<#44811#> <#44812#>'<#44812#><#44813#>Adam<#44813#> <#44814#>1)<#44814#> 
       <#44815#>(add-to-address-book<#44815#> <#44816#>'<#44816#><#44817#>Eve<#44817#> <#44818#>2)<#44818#> 
       <#44819#>(add-to-address-book<#44819#> <#44820#>'<#44820#><#44821#>Chris<#44821#> <#44822#>6145384))<#44822#> 
The first subexpression is a plain function application. So, the first step relies on the usual law of substitution:
 
<#44831#>(define<#44831#> <#44832#>address-book<#44832#> <#44833#>empty)<#44833#> 
<#44834#>(begin<#44834#> <#44835#>(set!<#44835#> <#44836#>address-book<#44836#> <#44837#>(cons<#44837#> <#44838#>(list<#44838#> <#44839#>'<#44839#><#44840#>Adam<#44840#> <#44841#>1)<#44841#> <#44842#>address-book))<#44842#> 
       <#44843#>(add-to-address-book<#44843#> <#44844#>'<#44844#><#44845#>Eve<#44845#> <#44846#>2)<#44846#> 
       <#44847#>(add-to-address-book<#44847#> <#44848#>'<#44848#><#44849#>Chris<#44849#> <#44850#>6145384))<#44850#> 
The next expression to be evaluated is the <#68132#><#44854#>set!<#44854#>-expression<#68132#> that is nested in the <#68133#><#44855#>begin<#44855#>-expression<#68133#>s, in particular its right-hand side. The first argument to <#68134#><#44856#>cons<#44856#><#68134#> is a value, but the second one is still a variable whose current value is <#68135#><#44857#>empty<#44857#><#68135#>. With this, we can see what happens next:
 
<#44862#>(define<#44862#> <#44863#>address-book<#44863#> <#44864#>empty)<#44864#> 
<#44865#>(begin<#44865#> <#44866#>(set!<#44866#> <#44867#>address-book<#44867#> <#44868#>(cons<#44868#> <#44869#>(list<#44869#> <#44870#>'<#44870#><#44871#>Adam<#44871#> <#44872#>1)<#44872#> <#44873#>empty))<#44873#> 
       <#44874#>(add-to-address-book<#44874#> <#44875#>'<#44875#><#44876#>Eve<#44876#> <#44877#>2)<#44877#> 
       <#44878#>(add-to-address-book<#44878#> <#44879#>'<#44879#><#44880#>Chris<#44880#> <#44881#>6145384))<#44881#> 
At this point we are ready to evaluate the <#68136#><#44885#>set!<#44885#>-expression<#68136#>. Specifically, we change the definition of <#68137#><#44886#>address-book<#44886#><#68137#> so that the variable now stands for <#68138#><#44887#>(cons<#44887#>\ <#44888#>(list<#44888#>\ <#44889#>'<#44889#><#44890#>Adam<#44890#>\ <#44891#>1)<#44891#>\ <#44892#>empty)<#44892#><#68138#>:
 
<#44897#>(d<#44897#><#44898#>efine<#44898#> <#44899#>address-book<#44899#> 
  <#44900#>(c<#44900#><#44901#>ons<#44901#> <#44902#>(list<#44902#> <#44903#>'<#44903#><#44904#>Adam<#44904#> <#44905#>1)<#44905#> 
    <#44906#>empty))<#44906#> 
<#44907#>(begin<#44907#> <#44908#>(<#44908#><#44909#>void<#44909#><#44910#>)<#44910#> 
       <#44911#>(add-to-address-book<#44911#> <#44912#>'<#44912#><#44913#>Eve<#44913#> <#44914#>2)<#44914#> 
       <#44915#>(add-to-address-book<#44915#> <#44916#>'<#44916#><#44917#>Chris<#44917#> <#44918#>6145384))<#44918#> 
The <#68139#><#44922#>begin<#44922#>-expression<#68139#> throws away the invisible value. Evaluating the remaining applications of <#68140#><#44923#>add-to-address-book<#44923#><#68140#> yields
 
<#44928#>(d<#44928#><#44929#>efine<#44929#> <#44930#>address-book<#44930#> 
  <#44931#>(list<#44931#> <#44932#>(list<#44932#> <#44933#>'<#44933#><#44934#>Chris<#44934#> <#44935#>6145384)<#44935#> 
        <#44936#>(list<#44936#> <#44937#>'<#44937#><#44938#>Eve<#44938#> <#44939#>2)<#44939#> 
        <#44940#>(list<#44940#> <#44941#>'<#44941#><#44942#>Adam<#44942#> <#44943#>1)))<#44943#> 
<#44944#>(<#44944#><#44945#>void<#44945#><#44946#>)<#44946#> 
In short, the three applications turn <#68141#><#44950#>address-book<#44950#><#68141#> into a list of three pairs. If we now evaluate <#68142#><#44951#>(lookup<#44951#>\ <#44952#>'<#44952#><#44953#>Adam<#44953#>\ <#44954#>address-book)<#44954#><#68142#> in the <#44955#>Interactions<#44955#> window again, we get <#68143#><#44956#>1<#44956#><#68143#>:
  <#44961#>(lookup<#44961#> <#44962#>'<#44962#><#44963#>Adam<#44963#> <#44964#>address-book)<#44964#>
<#44965#>=<#44965#> <#44966#>(lookup<#44966#> <#44967#>'<#44967#><#44968#>Adam<#44968#> <#44969#>(list<#44969#> <#44970#>(list<#44970#> <#44971#>'<#44971#><#44972#>Chris<#44972#> <#44973#>6145384)<#44973#> 
                      <#44974#>(list<#44974#> <#44975#>'<#44975#><#44976#>Eve<#44976#> <#44977#>2)<#44977#> 
                      <#44978#>(list<#44978#> <#44979#>'<#44979#><#44980#>Adam<#44980#> <#44981#>1))<#44981#> 
<#44982#>=<#44982#> <#44983#>...<#44983#> 
<#44984#>=<#44984#> <#44985#>1<#44985#> 
The comparison of this evaluation and the one at the beginning of the section shows how <#68144#><#44989#>set!<#44989#><#68144#> changes the meaning of <#68145#><#44990#>address-book<#44990#><#68145#> over time and how the two functions, <#68146#><#44991#>add-to-address-book<#44991#><#68146#> and <#68147#><#44992#>lookup<#44992#><#68147#>, implement the services that we discussed in section~#secmemory#44993>. The exercises show useful this collaboration of two functions is in the context of a graphical user interface.
<#44996#>Exercise 35.4.1<#44996#> The software for managing address books permits users to remove entries. Develop the function
<#71704#>;; <#68148#><#45002#>remove<#45002#> <#45003#>:<#45003#> <#45004#>symbol<#45004#> <#45005#><#45005#><#45006#>-;SPMgt;<#45006#><#45007#><#45007#> <#45008#>void<#45008#><#68148#><#71704#>
<#45009#>(define<#45009#> <#45010#>(remove<#45010#> <#45011#>name)<#45011#> <#45012#>...)<#45012#> 
which changes <#68149#><#45016#>address-book<#45016#><#68149#> so that all future <#68150#><#45017#>lookup<#45017#><#68150#>s for <#68151#><#45018#>name<#45018#><#68151#> yield <#68152#><#45019#>false<#45019#><#68152#>.~ external Solution<#68153#><#68153#> <#45025#>Exercise 35.4.2<#45025#> The teachpack <#45027#>phone-book.ss<#45027#> implements a graphical user interface based on the model-view pattern discussed in section~#secgui1#45028>. Figure~#figpbgui#45029> shows what the graphical user interface offers:
  1. a text-field for entering a name;
  2. a text-field for displaying the search result and for entering a phone number;
  3. a button for looking up the phone number for a name;
  4. a button for adding a name and a phone number; and
  5. a button for removing the phone number for a name.
Use the teachpack's <#68154#><#45032#>connect<#45032#><#68154#> function to create a GUI for the functions in this section and in exercise~#exsetpbremove#45033>. The function has the following contract, purpose, and header:
<#71705#>;; <#68155#><#45038#>model-T<#45038#> <#45039#>=<#45039#> <#45040#>(button%<#45040#> <#45041#>control-event%<#45041#> <#45042#><#45042#><#45043#>-;SPMgt;<#45043#><#45044#><#45044#> <#45045#>true<#45045#><#45046#>)<#45046#><#68155#><#71705#>
<#71706#>;; <#68156#><#45047#>connect<#45047#> <#45048#>:<#45048#> <#45049#>model-T<#45049#> <#45050#>model-T<#45050#> <#45051#>model-T<#45051#> <#45052#><#45052#><#45053#>-;SPMgt;<#45053#><#45054#><#45054#> <#45055#>true<#45055#><#68156#><#71706#> 
<#45056#>(define<#45056#> <#45057#>(connect<#45057#> <#45058#>lookup-cb<#45058#> <#45059#>change-cb<#45059#> <#45060#>remove-cb)<#45060#> <#45061#>...)<#45061#> 
That is, it consumes three model functions and wires them up with the GUI. The names of the parameters specify which call-back function goes with which button. A model function may obtain the contents of the name field with <#68157#><#45065#>(name-control)<#45065#><#68157#> and the contents of the number field with <#68158#><#45066#>(number-field)<#45066#><#68158#>.~ external Solution<#68159#><#68159#>