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#>.~ 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:
- a text-field for entering a name;
- a text-field for displaying the search result and for entering a phone number;
- a button for looking up the phone number for a name;
- a button for adding a name and a phone number; and
- 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#>.~ Solution<#68159#><#68159#>