<#56026#>Using Functions as Arguments<#56026#>:\ Instead of accepting <#69815#><#56027#>'<#56027#><#56028#>father<#56028#><#69815#>
and <#69816#><#56029#>'<#56029#><#56030#>mother<#56030#><#69816#> for <#69817#><#56031#>anc<#56031#><#69817#>, the function could also accept one
of the two structure mutators: <#69818#><#56032#>set-child-father!<#56032#><#69818#> or
<#69819#><#56033#>set-child-mother!<#56033#><#69819#>. Modify <#69820#><#56034#>add-ftn!<#56034#><#69820#>
accordingly.~ Solution<#69821#><#69821#>
<#56040#>Exercise 41.3.4<#56040#>
Suppose we wish to simulate a card game as a program. Each card has two
important characteristics: its <#55682#>suit<#55682#> and its <#55683#>rank<#55683#>. A player's
collection of cards is called a <#55684#>hand<#55684#>. For now we also assume that
every player has at least one card, that is, a hand is never empty.
Figure~#figcards#55685><#72025#>;; <#69752#><#55700#>create-hand<#55700#> <#55701#>:<#55701#> <#55702#>rank<#55702#> <#55703#>suit<#55703#> <#55704#><#55704#><#55705#>-;SPMgt;<#55705#><#55706#><#55706#> <#55707#>hand<#55707#><#69752#><#72025#>
<#72026#>;; to create a single-card hand from <#69753#><#55708#>r<#55708#><#69753#> and <#69754#><#55709#>s<#55709#><#69754#><#72026#>
<#55710#>(d<#55710#><#55711#>efine<#55711#> <#55712#>(create-hand<#55712#> <#55713#>r<#55713#> <#55714#>s)<#55714#>
<#55715#>(make-hand<#55715#> <#55716#>r<#55716#> <#55717#>s<#55717#> <#55718#>empty))<#55718#>
The function consumes the properties of a card; it creates a hand with one
card and no others.
Adding a card to the end of a hand is a more difficult task than that. To
simplify our life a bit, let's say that a player always adds new cards to
the end of the hand. In this case we must process an arbitrarily large
value, which means we need a recursive function. Here is contract, effect
statement, and header:
<#72027#>;; <#69755#><#55728#>add-at-end!<#55728#> <#55729#>:<#55729#> <#55730#>rank<#55730#> <#55731#>suit<#55731#> <#55732#>hand<#55732#> <#55733#><#55733#><#55734#>-;SPMgt;<#55734#><#55735#><#55735#> <#55736#>void<#55736#><#69755#><#72027#>
<#72028#>;; effect : to add a card with <#69756#><#55737#>r<#55737#><#69756#> as rank and <#69757#><#55738#>s<#55738#><#69757#> as suit at the end <#72028#>
<#55739#>(define<#55739#> <#55740#>(add-at-end!<#55740#> <#55741#>rank<#55741#> <#55742#>suit<#55742#> <#55743#>a-hand)<#55743#> <#55744#>...)<#55744#>
These specifications say that the function has the invisible value as the
result and that it communicates with the rest of the program exclusively
through its effects.
Let's start with examples:
<#55752#>(define<#55752#> <#55753#>hand0<#55753#> <#55754#>(create-hand<#55754#> <#55755#>13<#55755#> <#55756#>SPADES))<#55756#>
If we were to evaluate the following expression
<#55764#>(add-at-end!<#55764#> <#55765#>1<#55765#> <#55766#>DIAMONDS<#55766#> <#55767#>hand0)<#55767#>
in the context of this definition, <#69758#><#55771#>hand0<#55771#><#69758#> becomes a card with two
hands: a spades-13 followed by a diamonds-1. Figure~#figbuildahand#55772><#55779#>(add-at-end!<#55779#> <#55780#>2<#55780#> <#55781#>CLUBS<#55781#> <#55782#>hand0))<#55782#>
in this context, <#69761#><#55786#>hand0<#55786#><#69761#> become a hand with three cards. The last
one is a clubs-2. In terms of an evaluation, the definition of
<#69762#><#55787#>hand0<#55787#><#69762#> should change to
<#55792#>(d<#55792#><#55793#>efine<#55793#> <#55794#>hand0<#55794#>
<#55795#>(m<#55795#><#55796#>ake-hand<#55796#> <#55797#>13<#55797#> <#55798#>SPADES<#55798#>
<#55799#>(m<#55799#><#55800#>ake-hand<#55800#> <#55801#>1<#55801#> <#55802#>DIAMONDS<#55802#>
<#55803#>(make-hand<#55803#> <#55804#>2<#55804#> <#55805#>CLUBS<#55805#> <#55806#>empty))))<#55806#>
after both additions have been carried out.
Given that the <#69763#><#55810#>rank<#55810#><#69763#> and <#69764#><#55811#>suit<#55811#><#69764#> argument to
<#69765#><#55812#>add-at-end!<#55812#><#69765#> are atomic values, the template must be based on the
data definition for <#69766#><#55813#>hand<#55813#><#69766#>s:
<#55818#>(d<#55818#><#55819#>efine<#55819#> <#55820#>(add-at-end!<#55820#> <#55821#>rank<#55821#> <#55822#>suit<#55822#> <#55823#>a-hand)<#55823#>
<#55824#>(c<#55824#><#55825#>ond<#55825#>
<#55826#>[<#55826#><#55827#>(empty?<#55827#> <#55828#>(hand-next<#55828#> <#55829#>a-hand))<#55829#>
<#55830#>...<#55830#> <#55831#>(hand-rank<#55831#> <#55832#>a-hand)<#55832#> <#55833#>...<#55833#> <#55834#>(hand-suit<#55834#> <#55835#>a-hand)<#55835#> <#55836#>...]<#55836#>
<#55837#>[<#55837#><#55838#>else<#55838#> <#55839#>...<#55839#> <#55840#>(hand-rank<#55840#> <#55841#>a-hand)<#55841#> <#55842#>...<#55842#> <#55843#>(hand-suit<#55843#> <#55844#>a-hand)<#55844#> <#55845#>...<#55845#>
<#55846#>...<#55846#> <#55847#>(add-at-end!<#55847#> <#55848#>rank<#55848#> <#55849#>suit<#55849#> <#55850#>(hand-next<#55850#> <#55851#>a-hand))<#55851#> <#55852#>...]<#55852#><#55853#>))<#55853#>
The template consists of two clauses, which check the content of the
<#69767#><#55857#>next<#55857#><#69767#> field of <#69768#><#55858#>a-hand<#55858#><#69768#>. It is recursive in the second
clause, because the data definition for <#69769#><#55859#>hand<#55859#><#69769#>s is self-referential
in that clause. In short, the template is completely conventional.
The next step is to consider how the function should affect <#69770#><#55860#>a-hand<#55860#><#69770#>
in each clause:
Here is the complete definition of <#69780#><#55885#>add-at-end!<#55885#><#69780#>:
<#55870#>(set-next-hand!<#55870#> <#55871#>a-hand<#55871#> <#55872#>(make-hand<#55872#> <#55873#>rank<#55873#> <#55874#>suit<#55874#> <#55875#>empty))<#55875#>
The newly created <#69775#><#55879#>hand<#55879#><#69775#> structure is now the one that contains
<#69776#><#55880#>empty<#55880#><#69776#> in its next field, that is, it is the new end of the
<#69777#><#55881#>a-hand<#55881#><#69777#> value.
<#72029#>;; <#69781#><#55890#>add-at-end!<#55890#> <#55891#>:<#55891#> <#55892#>rank<#55892#> <#55893#>suit<#55893#> <#55894#>hand<#55894#> <#55895#><#55895#><#55896#>-;SPMgt;<#55896#><#55897#><#55897#> <#55898#>void<#55898#><#69781#><#72029#>
<#72030#>;; effect: to add a card with v as rank and s as suit at the end of <#69782#><#55899#>a-hand<#55899#><#69782#><#72030#>
<#55900#>(d<#55900#><#55901#>efine<#55901#> <#55902#>(add-at-end!<#55902#> <#55903#>rank<#55903#> <#55904#>suit<#55904#> <#55905#>a-hand)<#55905#>
<#55906#>(c<#55906#><#55907#>ond<#55907#>
<#55908#>[<#55908#><#55909#>(empty?<#55909#> <#55910#>(hand-next<#55910#> <#55911#>a-hand))<#55911#>
<#55912#>(set-hand-next!<#55912#> <#55913#>a-hand<#55913#> <#55914#>(make-hand<#55914#> <#55915#>rank<#55915#> <#55916#>suit<#55916#> <#55917#>empty))]<#55917#>
<#55918#>[<#55918#><#55919#>else<#55919#> <#55920#>(add-at-end!<#55920#> <#55921#>rank<#55921#> <#55922#>suit<#55922#> <#55923#>(hand-next<#55923#> <#55924#>a-hand))]<#55924#><#55925#>))<#55925#>
It closely resembles the list-processing functions we designed in
part~#partstructural#55929>
<#55933#>Exercise 41.3.1<#55933#>
<#55939#>(define<#55939#> <#55940#>hand0<#55940#> <#55941#>(create-hand<#55941#> <#55942#>13<#55942#> <#55943#>SPADES))<#55943#>
<#55944#>(b<#55944#><#55945#>egin<#55945#>
<#55946#>(add-at-end!<#55946#> <#55947#>1<#55947#> <#55948#>DIAMONDS<#55948#> <#55949#>hand0)<#55949#>
<#55950#>(add-at-end!<#55950#> <#55951#>2<#55951#> <#55952#>CLUBS<#55952#> <#55953#>hand0)<#55953#>
<#55954#>hand0)<#55954#>
Test the function with this example.
Make up two other examples. Recall that each example consists of an initial
hand, cards to be added, and a prediction of what the result should
be. Then test the function with the additional examples. Formulate the
tests as boolean-valued expressions.~ Solution<#69784#><#69784#>
<#55963#>Exercise 41.3.2<#55963#>
<#55979#>(define-struct<#55979#> <#55980#>child<#55980#> <#55981#>(name<#55981#> <#55982#>social<#55982#> <#55983#>father<#55983#> <#55984#>mother))<#55984#>
and a data definition:
A <#69789#><#55989#>family tree node<#55989#><#69789#> (short: <#69790#><#55990#>ftn<#55990#><#69790#>) is either
For here, we assume that everyone has a social security number
and that social security numbers are unique.
Following our convention from part~#partadvanced#56005>
Not all mutator functions are as easily designed as the
<#69826#><#56052#>add-at-end!<#56052#><#69826#> function. Indeed, in some cases things don't even work
out at all. Let's consider two additional services. The first one removes
the last card in a hand. Its contract and effect statement are variations
on those for <#69827#><#56053#>add-at-end!<#56053#><#69827#>:
<#72031#>;; <#69828#><#56058#>remove-last!<#56058#> <#56059#>:<#56059#> <#56060#>hand<#56060#> <#56061#><#56061#><#56062#>-;SPMgt;<#56062#><#56063#><#56063#> <#56064#>void<#56064#><#69828#><#72031#>
<#72032#>;; effect : to remove the last card in <#69829#><#56065#>a-hand<#56065#><#69829#>, unless it is the only one<#72032#>
<#56066#>(define<#56066#> <#56067#>(remove-last!<#56067#> <#56068#>a-hand)<#56068#> <#56069#>...)<#56069#>
The effect is restricted because a hand must always contain one card.
We can also adapt the example for <#69830#><#56073#>add-at-end!<#56073#><#69830#> without difficulty:
<#56078#>(define<#56078#> <#56079#>hand0<#56079#> <#56080#>(create-hand<#56080#> <#56081#>13<#56081#> <#56082#>SPADES))<#56082#>
<#56083#>(b<#56083#><#56084#>egin<#56084#>
<#56085#>(add-at-end!<#56085#> <#56086#>1<#56086#> <#56087#>DIAMONDS<#56087#> <#56088#>hand0)<#56088#>
<#56089#>(add-at-end!<#56089#> <#56090#>2<#56090#> <#56091#>CLUBS<#56091#> <#56092#>hand0)<#56092#>
<#56093#>(remove-last!<#56093#> <#56094#>hand0)<#56094#>
<#56095#>(remove-last!<#56095#> <#56096#>hand0))<#56096#>
The resulting value is <#69831#><#56100#>void<#56100#><#69831#>. The effect of the computation is to
return <#69832#><#56101#>hand0<#56101#><#69832#> in its initial state.
The template for <#69833#><#56102#>remove-last!<#56102#><#69833#> is the same as that for
<#69834#><#56103#>add-at-end!<#56103#><#69834#> because both functions process the same class of
values. So the next step is to analyze what effects the function must
compute for each case in the template:
The analysis of the first clause suggests the use of an accumulator. We
tried the natural route and discovered that knowledge is lost during an
evaluation, which is the criterium for considering a switch to an
accumulator-based design recipe.
Once we have recognized the need for an accumulator-style function, we
encapsulate the template in a <#69845#><#56118#>local<#56118#>-expression<#69845#> and add an
accumulator argument to its definition and applications:
But we can't know whether or not <#69843#><#56115#>a-hand<#56115#><#69843#> is the last item in a long
chain of <#69844#><#56116#>hand<#56116#><#69844#>s or the only one. We have lost knowledge that was
available at the beginning of the evaluation!
<#56123#>(d<#56123#><#56124#>efine<#56124#> <#56125#>(remove-last!<#56125#> <#56126#>a-hand0)<#56126#>
<#56127#>(l<#56127#><#56128#>ocal<#56128#> <#56129#>(<#56129#><#72033#>;; <#69846#><#56130#>accumulator<#56130#><#69846#> ...<#72033#>
<#56131#>(d<#56131#><#56132#>efine<#56132#> <#56133#>(rem!<#56133#> <#56134#>a-hand<#56134#> <#56135#>accumulator)<#56135#>
<#56136#>(c<#56136#><#56137#>ond<#56137#>
<#56138#>[<#56138#><#56139#>(empty?<#56139#> <#56140#>(hand-next<#56140#> <#56141#>a-hand))<#56141#>
<#56142#>...<#56142#> <#56143#>(hand-rank<#56143#> <#56144#>a-hand)<#56144#> <#56145#>...<#56145#> <#56146#>(hand-suit<#56146#> <#56147#>a-hand)<#56147#> <#56148#>...]<#56148#>
<#56149#>[<#56149#><#56150#>else<#56150#> <#56151#>...<#56151#> <#56152#>(hand-rank<#56152#> <#56153#>a-hand)<#56153#> <#56154#>...<#56154#> <#56155#>(hand-suit<#56155#> <#56156#>a-hand)<#56156#> <#56157#>...<#56157#>
<#56158#>...<#56158#> <#56159#>(rem!<#56159#> <#56160#>(hand-next<#56160#> <#56161#>a-hand)<#56161#> <#56162#>...<#56162#>
The questions to ask now are what the accumulator represents and what its
first value is.
The best way to understand the nature of accumulators is to study why the
plain structural design of <#69848#><#56175#>remove-last!<#56175#><#69848#> failed. Hence, we return
to the analysis of our first clause in the template. When <#69849#><#56176#>rem!<#56176#><#69849#>
reaches that clause, two things should have been accomplished. First,
<#69850#><#56177#>rem!<#56177#><#69850#> should know that <#69851#><#56178#>a-hand<#56178#><#69851#> is not the only
<#69852#><#56179#>hand<#56179#><#69852#> structure in <#69853#><#56180#>a-hand0<#56180#><#69853#>. Second, <#69854#><#56181#>rem!<#56181#><#69854#> must be
enabled to remove <#69855#><#56182#>a-hand<#56182#><#69855#> from <#69856#><#56183#>a-hand0<#56183#><#69856#>. For the first
goal, <#69857#><#56184#>rem!<#56184#><#69857#>'s first application should be in a context where we
know that <#69858#><#56185#>a-hand0<#56185#><#69858#> contains more than one card. This argument
suggests a <#69859#><#56186#>cond<#56186#>-expression<#69859#> for the body of the <#69860#><#56187#>local<#56187#>-expression<#69860#>:
<#56192#>(c<#56192#><#56193#>ond<#56193#>
<#56194#>[<#56194#><#56195#>(empty?<#56195#> <#56196#>(hand-next<#56196#> <#56197#>a-hand))<#56197#> <#56198#>(<#56198#><#56199#>void<#56199#><#56200#>)]<#56200#>
<#56201#>[<#56201#><#56202#>else<#56202#> <#56203#>(rem!<#56203#> <#56204#>a-hand0<#56204#> <#56205#>...)]<#56205#><#56206#>)<#56206#>
For the second goal, <#69861#><#56210#>rem!<#56210#><#69861#>'s accumulator argument should always
represent the <#69862#><#56211#>hand<#56211#><#69862#> structure that preceeds <#69863#><#56212#>a-hand<#56212#><#69863#> in
<#69864#><#56213#>a-hand0<#56213#><#69864#>. Then <#69865#><#56214#>rem!<#56214#><#69865#> can remove <#69866#><#56215#>a-hand<#56215#><#69866#> by
modifying the predecessor's <#69867#><#56216#>next<#56216#><#69867#> field:
<#56221#>(set-hand-next!<#56221#> <#56222#>accumulator<#56222#> <#56223#>empty)<#56223#>
Now the pieces of the design puzzle fall into place. The complete
definition of the function is in figure~#figdefremovelast#56227><#72034#>;; <#69874#><#56239#>remove-last!<#56239#> <#56240#>:<#56240#> <#56241#>hand<#56241#> <#56242#><#56242#><#56243#>-;SPMgt;<#56243#><#56244#><#56244#> <#56245#>void<#56245#><#69874#><#72034#>
<#72035#>;; effect : to remove the last card in <#69875#><#56246#>a-hand0<#56246#><#69875#>, unless it is the only one<#72035#>
<#56247#>(d<#56247#><#56248#>efine<#56248#> <#56249#>(remove-last!<#56249#> <#56250#>a-hand0)<#56250#>
<#56251#>(l<#56251#><#56252#>ocal<#56252#> <#56253#>(<#56253#><#72036#>;; <#69876#><#56254#>predecessor-of:a-hand<#56254#><#69876#> represents the predecessor of<#72036#>
<#72037#>;; <#69877#><#56255#>a-hand<#56255#><#69877#> in the <#69878#><#56256#>a-hand0<#56256#><#69878#> chain <#72037#>
<#56257#>(d<#56257#><#56258#>efine<#56258#> <#56259#>(rem!<#56259#> <#56260#>a-hand<#56260#> <#56261#>predecessor-of:a-hand)<#56261#>
<#56262#>(c<#56262#><#56263#>ond<#56263#>
<#56264#>[<#56264#><#56265#>(empty?<#56265#> <#56266#>(hand-next<#56266#> <#56267#>a-hand))<#56267#>
<#56268#>(set-hand-next!<#56268#> <#56269#>predecessor-of:a-hand<#56269#> <#56270#>empty)]<#56270#>
<#56271#>[<#56271#><#56272#>else<#56272#> <#56273#>(rem!<#56273#> <#56274#>(hand-next<#56274#> <#56275#>a-hand)<#56275#> <#56276#>a-hand)]<#56276#><#56277#>)))<#56277#>
<#56278#>(c<#56278#><#56279#>ond<#56279#>
<#56280#>[<#56280#><#56281#>(empty?<#56281#> <#56282#>(hand-next<#56282#> <#56283#>a-hand0))<#56283#> <#56284#>(<#56284#><#56285#>void<#56285#><#56286#>)]<#56286#>
<#56287#>[<#56287#><#56288#>else<#56288#> <#56289#>(rem!<#56289#> <#56290#>(hand-next<#56290#> <#56291#>a-hand0)<#56291#> <#56292#>a-hand0)]<#56292#><#56293#>)))<#56293#>
Both applications of <#69879#><#56297#>rem!<#56297#><#69879#> have the shape
<#56302#>(rem!<#56302#> <#56303#>(hand-next<#56303#> <#56304#>a-hand)<#56304#> <#56305#>a-hand)<#56305#>
<#56309#>Figure: Removing the last card<#56309#>
It is now time to revisit the basic assumption about the card game that the
cards are added to the end of a hand. When human players pick up cards,
they hardly ever just add them to the end. Instead, many use some special
arrangement and maintain it over the course of a game. Some arrange hands
according to suits, others according to rank, and yet others according to
both criteria.
Let's consider an operation for inserting a card into a <#69880#><#56311#>hand<#56311#><#69880#> based
on its rank:
<#72038#>;; <#69881#><#56316#>sorted-insert!<#56316#> <#56317#>:<#56317#> <#56318#>rank<#56318#> <#56319#>suit<#56319#> <#56320#>hand<#56320#> <#56321#><#56321#><#56322#>-;SPMgt;<#56322#><#56323#><#56323#> <#56324#>void<#56324#><#69881#><#72038#>
<#72039#>;; assume: <#69882#><#56325#>a-hand<#56325#><#69882#> is sorted by rank, in descending order<#72039#>
<#72040#>;; effect: to add a card with <#69883#><#56326#>r<#56326#><#69883#> as rank and <#69884#><#56327#>s<#56327#><#69884#> as suit at the proper place<#72040#>
<#56328#>(define<#56328#> <#56329#>(sorted-insert!<#56329#> <#56330#>r<#56330#> <#56331#>s<#56331#> <#56332#>a-hand)<#56332#> <#56333#>...)<#56333#>
The function assumes that the given <#69885#><#56337#>hand<#56337#><#69885#> is already sorted. The
assumption naturally holds if we always use <#69886#><#56338#>create-hand<#56338#><#69886#> to create
a hand and <#69887#><#56339#>sorted-insert!<#56339#><#69887#> to insert cards.
Suppose we start with the same hand as above for <#69888#><#56340#>add-at-end!<#56340#><#69888#>:
<#56345#>(define<#56345#> <#56346#>hand0<#56346#> <#56347#>(create-hand<#56347#> <#56348#>13<#56348#> <#56349#>SPADES))<#56349#>
If we evaluate <#69889#><#56353#>(sorted-insert!<#56353#>\ <#56354#>1<#56354#>\ <#56355#>DIAMONDS<#56355#>\ <#56356#>hand0)<#56356#><#69889#> in this context,
<#69890#><#56357#>hands0<#56357#><#69890#> becomes
<#56362#>(m<#56362#><#56363#>ake-hand<#56363#> <#56364#>13<#56364#> <#56365#>SPADES<#56365#>
<#56366#>(make-hand<#56366#> <#56367#>1<#56367#> <#56368#>DIAMONDS<#56368#> <#56369#>empty))<#56369#>
If we now evaluate <#69891#><#56373#>(sorted-insert!<#56373#>\ <#56374#>1<#56374#>\ <#56375#>CLUBS<#56375#>\ <#56376#>hand0)<#56376#><#69891#> in addition,
we get
<#56381#>(m<#56381#><#56382#>ake-hand<#56382#> <#56383#>13<#56383#> <#56384#>SPADES<#56384#>
<#56385#>(m<#56385#><#56386#>ake-hand<#56386#> <#56387#>2<#56387#> <#56388#>CLUBS<#56388#>
<#56389#>(make-hand<#56389#> <#56390#>1<#56390#> <#56391#>DIAMONDS<#56391#> <#56392#>empty)))<#56392#>
for <#69892#><#56396#>hand0<#56396#><#69892#>. This value shows what it means for a chain to be
sorted in descending order. As we traverse the chain, the ranks get smaller
and smaller independent of what the suits are.
Our next step is to analyze the template. Here is the template, adapted to
our present purpose:
<#56401#>(d<#56401#><#56402#>efine<#56402#> <#56403#>(sorted-insert!<#56403#> <#56404#>r<#56404#> <#56405#>s<#56405#> <#56406#>a-hand)<#56406#>
<#56407#>(c<#56407#><#56408#>ond<#56408#>
<#56409#>[<#56409#><#56410#>(empty?<#56410#> <#56411#>(hand-next<#56411#> <#56412#>a-hand))<#56412#>
<#56413#>...<#56413#> <#56414#>(hand-rank<#56414#> <#56415#>a-hand)<#56415#> <#56416#>...<#56416#> <#56417#>(hand-suit<#56417#> <#56418#>a-hand)<#56418#> <#56419#>...]<#56419#>
<#56420#>[<#56420#><#56421#>e<#56421#><#56422#>lse<#56422#> <#56423#>...<#56423#> <#56424#>(hand-rank<#56424#> <#56425#>a-hand)<#56425#> <#56426#>...<#56426#> <#56427#>(hand-suit<#56427#> <#56428#>a-hand)<#56428#> <#56429#>...<#56429#>
<#56430#>...<#56430#> <#56431#>(sorted-insert!<#56431#> <#56432#>r<#56432#> <#56433#>s<#56433#> <#56434#>(hand-next<#56434#> <#56435#>a-hand))<#56435#> <#56436#>...]<#56436#><#56437#>))<#56437#>
The key step of the function is to insert the new card between two cards
such that first card's rank is larger than, or equal to, <#69893#><#56441#>r<#56441#><#69893#> and
<#69894#><#56442#>r<#56442#><#69894#> is larger than, or equal to, the rank of the second. Because
we only have two cards in the second clause, we start by formulating the
answer for the second clause. The condition we just specified implies that
we need a nested <#69895#><#56443#>cond<#56443#>-expression<#69895#>:
<#56448#>(c<#56448#><#56449#>ond<#56449#>
<#56450#>[<#56450#><#56451#>(;SPMgt;=<#56451#> <#56452#>(hand-rank<#56452#> <#56453#>a-hand)<#56453#> <#56454#>r<#56454#> <#56455#>(hand-rank<#56455#> <#56456#>(hand-next<#56456#> <#56457#>a-hand)))<#56457#> <#56458#>...]<#56458#>
<#56459#>[<#56459#><#56460#>else<#56460#> <#56461#>...]<#56461#><#56462#>)<#56462#>
The first condition expresses in Scheme what we just discussed. In
particular, <#69896#><#56466#>(hand-rank<#56466#>\ <#56467#>a-hand)<#56467#><#69896#> picks the rank of the first card in
<#69897#><#56468#>a-hand<#56468#><#69897#> and <#69898#><#56469#>(hand-rank<#56469#>\ <#56470#>(hand-next<#56470#>\ <#56471#>a-hand))<#56471#><#69898#> picks the rank
of the second one. The comparison determines whether the three ranks are
properly ordered.
Each case of this new <#69899#><#56472#>cond<#56472#>-expression<#69899#> deserves its own analysis:
Putting all the pieces together yields a partial function definition:
<#56493#>(c<#56493#><#56494#>ond<#56494#>
<#56495#>[<#56495#><#56496#>(;SPMgt;=<#56496#> <#56497#>(hand-rank<#56497#> <#56498#>a-hand)<#56498#> <#56499#>r<#56499#> <#56500#>(hand-rank<#56500#> <#56501#>(hand-next<#56501#> <#56502#>a-hand)))<#56502#>
<#56503#>(set-hand-next!<#56503#> <#56504#>a-hand<#56504#> <#56505#>(make-hand<#56505#> <#56506#>r<#56506#> <#56507#>s<#56507#> <#56508#>(hand-next<#56508#> <#56509#>a-hand)))]<#56509#>
<#56510#>[<#56510#><#56511#>else<#56511#> <#56512#>...]<#56512#><#56513#>)<#56513#>
<#56530#>(d<#56530#><#56531#>efine<#56531#> <#56532#>(sorted-insert!<#56532#> <#56533#>r<#56533#> <#56534#>s<#56534#> <#56535#>a-hand)<#56535#>
<#56536#>(c<#56536#><#56537#>ond<#56537#>
<#56538#>[<#56538#><#56539#>(empty?<#56539#> <#56540#>(hand-next<#56540#> <#56541#>a-hand))<#56541#>
<#56542#>...<#56542#> <#56543#>(hand-rank<#56543#> <#56544#>a-hand)<#56544#> <#56545#>...<#56545#> <#56546#>(hand-suit<#56546#> <#56547#>a-hand)<#56547#> <#56548#>...]<#56548#>
<#56549#>[<#56549#><#56550#>e<#56550#><#56551#>lse<#56551#>
<#56552#>(c<#56552#><#56553#>ond<#56553#>
<#56554#>[<#56554#><#56555#>(;SPMgt;=<#56555#> <#56556#>(hand-rank<#56556#> <#56557#>a-hand)<#56557#> <#56558#>r<#56558#> <#56559#>(hand-rank<#56559#> <#56560#>(hand-next<#56560#> <#56561#>a-hand)))<#56561#>
<#56562#>(set-hand-next!<#56562#> <#56563#>a-hand<#56563#> <#56564#>(make-hand<#56564#> <#56565#>r<#56565#> <#56566#>s<#56566#> <#56567#>(hand-next<#56567#> <#56568#>a-hand)))]<#56568#>
<#56569#>[<#56569#><#56570#>else<#56570#> <#56571#>(sorted-insert!<#56571#> <#56572#>r<#56572#> <#56573#>s<#56573#> <#56574#>(hand-next<#56574#> <#56575#>a-hand))]<#56575#><#56576#>)]<#56576#><#56577#>))<#56577#>
The only remaining gaps are now in the first clause.
The difference between the first and the second <#69911#><#56581#>cond<#56581#><#69911#>-clause is
that there is no second <#69912#><#56582#>hand<#56582#><#69912#> structure in the first clause so that
we cannot compare ranks. Still, we can compare <#69913#><#56583#>r<#56583#><#69913#> and
<#69914#><#56584#>(hand-rank<#56584#>\ <#56585#>a-hand)<#56585#><#69914#> and compute something based on the outcome of
this comparison:
<#56590#>(c<#56590#><#56591#>ond<#56591#>
<#56592#>[<#56592#><#56593#>(;SPMgt;=<#56593#> <#56594#>(hand-rank<#56594#> <#56595#>a-hand)<#56595#> <#56596#>r)<#56596#> <#56597#>...]<#56597#>
<#56598#>[<#56598#><#56599#>else<#56599#> <#56600#>...]<#56600#><#56601#>)<#56601#>
Clearly, if the comparison expression evaluates to <#69915#><#56605#>true<#56605#><#69915#>, the
function must mutate the <#69916#><#56606#>next<#56606#><#69916#> field of <#69917#><#56607#>a-hand<#56607#><#69917#> and add a
new <#69918#><#56608#>hand<#56608#><#69918#> structure:
<#56613#>(c<#56613#><#56614#>ond<#56614#>
<#56615#>[<#56615#><#56616#>(;SPMgt;=<#56616#> <#56617#>(hand-rank<#56617#> <#56618#>a-hand)<#56618#> <#56619#>r)<#56619#>
<#56620#>(set-hand-next!<#56620#> <#56621#>a-hand<#56621#> <#56622#>(make-hand<#56622#> <#56623#>r<#56623#> <#56624#>s<#56624#> <#56625#>empty))]<#56625#>
<#56626#>[<#56626#><#56627#>else<#56627#> <#56628#>...]<#56628#><#56629#>)<#56629#>
The problem is that we have nothing to mutate in the second clause. If
<#69919#><#56633#>r<#56633#><#69919#> is larger than the rank of <#69920#><#56634#>a-hand<#56634#><#69920#>, the new card should
be inserted between the predecessor of <#69921#><#56635#>a-hand<#56635#><#69921#> and <#69922#><#56636#>a-hand<#56636#><#69922#>.
But that kind of situation would have been discovered by the second
clause. The seeming contradiction suggests that the dots in the second
clause are a response to a singular case:
The dots are only evaluated if <#69923#><#56638#>sorted-insert!<#56638#><#69923#> consumes a rank
<#69924#><#56639#>r<#56639#><#69924#> that is larger than all the values in the <#69925#><#56640#>rank<#56640#><#69925#> fields
of <#69926#><#56641#>a-hand<#56641#><#69926#>.
In that singular case, <#69927#><#56643#>a-hand<#56643#><#69927#> shouldn't change at all. After all,
there is no way to create a descending chain of cards by mutating
<#69928#><#56644#>a-hand<#56644#><#69928#> or any of its embedded <#69929#><#56645#>hand<#56645#><#69929#> structures.
At first glance, we can overcome the problem with a <#69930#><#56646#>set!<#56646#><#69930#>
expression that changes the definition of <#69931#><#56647#>hand0<#56647#><#69931#>:
<#56652#>(set!<#56652#> <#56653#>hand0<#56653#> <#56654#>(make-hand<#56654#> <#56655#>r<#56655#> <#56656#>s<#56656#> <#56657#>hand0))<#56657#>
This fix doesn't work in general though, because we can't assume that we
know which variable definition must be modified. Since expressions can be
abstracted over values but not variables, there is also no way to abstract
over <#69932#><#56661#>hand0<#56661#><#69932#> in this <#56662#>set!<#56662#>-expression.
A <#69933#><#56664#>hand<#56664#><#69933#> is an interface:
<#72041#>;; <#69936#><#56680#>create-hand<#56680#> <#56681#>:<#56681#> <#56682#>rank<#56682#> <#56683#>suit<#56683#> <#56684#><#56684#><#56685#>-;SPMgt;<#56685#><#56686#><#56686#> <#56687#>hand<#56687#><#69936#><#72041#>
<#72042#>;; to create a <#69937#><#56688#>hand<#56688#><#69937#> from the <#69938#><#56689#>rank<#56689#><#69938#> and <#69939#><#56690#>suit<#56690#><#69939#> of a single card<#72042#>
<#56691#>(d<#56691#><#56692#>efine<#56692#> <#56693#>(create-hand<#56693#> <#56694#>rank<#56694#> <#56695#>suit)<#56695#>
<#56696#>(l<#56696#><#56697#>ocal<#56697#> <#56698#>(<#56698#><#56699#>(define-struct<#56699#> <#56700#>hand<#56700#> <#56701#>(rank<#56701#> <#56702#>suit<#56702#> <#56703#>next))<#56703#>
<#56704#>(define<#56704#> <#56705#>the-hand<#56705#> <#56706#>(make-hand<#56706#> <#56707#>rank<#56707#> <#56708#>suit<#56708#> <#56709#>empty))<#56709#>
<#72043#>;; <#69940#><#56710#>insert-aux!<#56710#> <#56711#>:<#56711#> <#56712#>rank<#56712#> <#56713#>suit<#56713#> <#56714#>hand<#56714#> <#56715#><#56715#><#56716#>-;SPMgt;<#56716#><#56717#><#56717#> <#56718#>void<#56718#><#69940#><#72043#>
<#56719#>;; assume: hand is sorted by rank in descending order<#56719#>
<#72044#>;; effect: to add a card with <#69941#><#56720#>r<#56720#><#69941#> as rank and <#69942#><#56721#>s<#56721#><#69942#> as suit<#72044#>
<#56722#>;; at the proper place<#56722#>
<#56723#>(d<#56723#><#56724#>efine<#56724#> <#56725#>(insert-aux!<#56725#> <#56726#>r<#56726#> <#56727#>s<#56727#> <#56728#>a-hand)<#56728#>
<#56729#>(c<#56729#><#56730#>ond<#56730#>
<#56731#>[<#56731#><#56732#>(empty?<#56732#> <#56733#>(hand-next<#56733#> <#56734#>a-hand))<#56734#>
<#56735#>(set-hand-next!<#56735#> <#56736#>a-hand<#56736#> <#56737#>(make-hand<#56737#> <#56738#>r<#56738#> <#56739#>s<#56739#> <#56740#>empty))]<#56740#>
<#56741#>[<#56741#><#56742#>else<#56742#> <#56743#>(c<#56743#><#56744#>ond<#56744#>
<#56745#>[<#56745#><#56746#>(;SPMgt;=<#56746#> <#56747#>(hand-rank<#56747#> <#56748#>a-hand)<#56748#>
<#56749#>r<#56749#>
<#56750#>(hand-rank<#56750#> <#56751#>(hand-next<#56751#> <#56752#>a-hand)))<#56752#>
<#56753#>(s<#56753#><#56754#>et-hand-next!<#56754#> <#56755#>a-hand<#56755#>
<#56756#>(make-hand<#56756#> <#56757#>r<#56757#> <#56758#>s<#56758#> <#56759#>(hand-next<#56759#> <#56760#>a-hand)))]<#56760#>
<#56761#>[<#56761#><#56762#>else<#56762#> <#56763#>(insert-aux!<#56763#> <#56764#>r<#56764#> <#56765#>s<#56765#> <#56766#>(hand-next<#56766#> <#56767#>a-hand))]<#56767#><#56768#>)]<#56768#><#56769#>))<#56769#>
<#56770#>...<#56770#>
<#56771#>(d<#56771#><#56772#>efine<#56772#> <#56773#>(service-manager<#56773#> <#56774#>msg)<#56774#>
<#56775#>(c<#56775#><#56776#>ond<#56776#>
<#56777#>[<#56777#><#56778#>(symbol=?<#56778#> <#56779#>msg<#56779#> <#56780#>'<#56780#><#56781#>insert!)<#56781#>
<#56782#>(l<#56782#><#56783#>ambda<#56783#> <#56784#>(r<#56784#> <#56785#>s)<#56785#>
<#56786#>(c<#56786#><#56787#>ond<#56787#>
<#56788#>[<#56788#><#56789#>(;SPMgt;<#56789#> <#56790#>r<#56790#> <#56791#>(hand-rank<#56791#> <#56792#>the-hand))<#56792#>
<#56793#>(set!<#56793#> <#56794#>the-hand<#56794#> <#56795#>(make-hand<#56795#> <#56796#>r<#56796#> <#56797#>s<#56797#> <#56798#>the-hand))]<#56798#>
<#56799#>[<#56799#><#56800#>else<#56800#> <#56801#>(insert-aux!<#56801#> <#56802#>rank<#56802#> <#56803#>suit<#56803#> <#56804#>the-hand)]<#56804#><#56805#>))]<#56805#>
<#56806#>[<#56806#><#56807#>else<#56807#> <#56808#>(error<#56808#> <#56809#>'<#56809#><#56810#>managed-hand<#56810#> <#56811#>``message<#56811#> <#56812#>not<#56812#> <#56813#>understood'')]<#56813#><#56814#>)))<#56814#>
<#56815#>manage))<#56815#>
<#56819#>Figure: Encapsulation and structure mutation for hands of cards<#56819#>
We're stuck. It is impossible to define <#69943#><#56821#>sorted-insert!<#56821#><#69943#>, at least
as specified above. The analysis suggests a remedy, however. If we
introduce a single variable that always stands for the current
<#69944#><#56822#>hand<#56822#><#69944#> structure, we can use a combindation of assignments and
structure mutators to insert a new card. The trick is not to let any other
part of the program refer to this variable or even change it. Otherwise a
simple <#69945#><#56823#>set!<#56823#><#69945#> won't work, as argued before. In other words, we need
a state variable for each <#69946#><#56824#>hand<#56824#><#69946#> structure, and we need to
encapsulate it in a <#69947#><#56825#>local<#56825#>-expression<#69947#>.
Figure~#fighandenc#56826>
<#56839#>Exercise 41.3.5<#56839#>
A <#69962#><#56871#>binary tree<#56871#><#69962#> (<#69963#><#56872#>BT<#56872#><#69963#>) is either
where the required structure definition is
where <#69966#><#56880#>soc<#56880#><#69966#> is a number, <#69967#><#56881#>pn<#56881#><#69967#> is a symbol, and <#69968#><#56882#>lft<#56882#><#69968#> and <#69969#><#56883#>rgt<#56883#><#69969#> are <#69970#><#56884#>BT<#56884#><#69970#>s. <#56891#>(define-struct<#56891#> <#56892#>node<#56892#> <#56893#>(ssn<#56893#> <#56894#>name<#56894#> <#56895#>left<#56895#> <#56896#>right))<#56896#>
A binary tree is a <#69971#><#56900#>binary search tree<#56900#><#69971#> if every <#69972#><#56901#>node<#56901#><#69972#>
structure contains a social security numbers that is larger than all those
in the left subtree and smaller than all those in the right subtree.
Develop the function <#69973#><#56902#>insert-bst!<#56902#><#69973#>. The function consumes a name
<#69974#><#56903#>n<#56903#><#69974#>, a social security number <#69975#><#56904#>s<#56904#><#69975#>, and a bst. It modifies the
bst so that it contains a new node with <#69976#><#56905#>n<#56905#><#69976#> and <#69977#><#56906#>s<#56906#><#69977#> while
maintaining it as a search tree.
Also develop the function <#69978#><#56907#>remove-bst!<#56907#><#69978#>, which removes a node with a
given social security number. It combines the two subtrees of the removed
node by inserting all the nodes from the right tree into the left
one.~ Solution<#69979#><#69979#>
The discussion in this subsection and the exercises suggest that adding or
removing items from linked structures is a messy task. Dealing with an
item in the middle of the linked structures is best done with
accumulator-style functions. Dealing with the first structure requires
encapsulation and management functions. In contrast, as
exercise~#exhandmostlyfunctional#56915>