Structural Design Recipes and Mutation, Part 2

In the preceding sections, we studied structure mutation for fields that contain atomic data. We know, however, that structures can contain structures. Starting in section~#secstructinstruct#55679>, we even encountered self-referential data definitions involving structures in structures. On occasion, processing such classes of data may also require mutations of structure fields that contain structures. In this section, we work through one such an example.

rawhtml63 <#55680#>Figure: Playing with cards<#55680#>


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> contains a screen shot of DrScheme with structure and data definitions for manipulating cards and hands. The program fragment does not introduce separate classes of cards and hands, but a single structure and a single data definitions for hands. A hand consists of a <#69743#><#55686#>hand<#55686#><#69743#> structure, which contains a <#69744#><#55687#>rank<#55687#><#69744#>, a <#69745#><#55688#>suit<#55688#><#69745#>, and a <#69746#><#55689#>next<#55689#><#69746#> field. The data definition shows that the next field may contain two kinds of values: <#69747#><#55690#>empty<#55690#><#69747#>, which means that there are no other cards, and a <#69748#><#55691#>hand<#55691#><#69748#> structure, which contains the remainder of the cards. From a global perspective, a <#69749#><#55692#>hand<#55692#><#69749#> forms a chain of cards; only the last one contains <#69750#><#55693#>empty<#55693#><#69750#> in the <#69751#><#55694#>next<#55694#><#69751#> field. At first, a player has no cards. Picking up the first card creates a hand. Others cards are then inserted into the existing hand as needed. This calls for two functions: one for creating a hand and another one for inserting a card into a hand. Because a hand exists only once and corresponds to a physical object, it is natural to think of the second functions as one that modifies an existing value rather than building a new one. For now, we accept this premise and explore its consequences. Creating a hand is a simple act and easy to implement as a function:
<#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.
rawhtml64 <#55722#>Figure: Building a hand<#55722#>
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> depicts the change of hand0; the top half displays the initial state of <#69759#><#55773#>hand0<#55773#><#69759#>, the lower half displays the state after <#69760#><#55774#>add-at-end!<#55774#><#69760#> has added a card. If we furthermore evaluate
<#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:
  1. In the first case, <#69771#><#55862#>a-hand<#55862#><#69771#>'s <#69772#><#55863#>next<#55863#><#69772#> field is <#69773#><#55864#>empty<#55864#><#69773#>. In that case, we can modify the <#69774#><#55865#>next<#55865#><#69774#> field so that it contains the new card:
    <#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.
  2. In the second case, the natural recursion adds a new card to the end of <#69778#><#55882#>a-hand<#55882#><#69778#>. Indeed, because the given <#69779#><#55883#>a-hand<#55883#><#69779#> isn't the last one in the chain, the natural recursion does everything that needs to be done.
Here is the complete definition of <#69780#><#55885#>add-at-end!<#55885#><#69780#>:
<#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>. This should come as no surprise, because <#69783#><#55930#>add-at-end!<#55930#><#69783#> processes values from a class that closely resembles the data definition of lists and the design recipes are formulated in a general manner.
<#55933#>Exercise 41.3.1<#55933#> Evaluate the following program by hand:
<#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.~ external Solution<#69784#><#69784#> <#55963#>Exercise 41.3.2<#55963#> Develop the function <#69785#><#55965#>last-card<#55965#><#69785#>. It consumes a <#69786#><#55966#>hand<#55966#><#69786#> and produces a list with the last card's rank and suit. How can we use this function to test the <#69787#><#55967#>add-at-end!<#55967#><#69787#> function?~ external Solution<#69788#><#69788#> <#55973#>Exercise 41.3.3<#55973#> Suppose a family tree consists of structures that record the name, social security number, and parents of a person. Describing such a tree requires a structure definition:
<#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
  1. <#69791#><#55992#>false<#55992#><#69791#>, or
  2. <#69792#><#55993#>(make-child<#55993#>\ <#55994#>name<#55994#>\ <#55995#>socsec<#55995#>\ <#55996#>f<#55996#>\ <#55997#>m)<#55997#><#69792#> where <#69793#><#55998#>name<#55998#><#69793#> is a symbol, <#69794#><#55999#>socsec<#55999#><#69794#> is a number, and <#69795#><#56000#>f<#56000#><#69795#> and <#69796#><#56001#>m<#56001#><#69796#> are <#56002#>ftn<#56002#>s.
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>, <#69797#><#56006#>false<#56006#><#69797#> represents a lack of knowledge about someone's father or mother. As we find out more information, though, we can add nodes to our family tree. Develop the function <#69798#><#56007#>add-ftn!<#56007#><#69798#>. It consumes a family tree <#69799#><#56008#>a-ft<#56008#><#69799#>, a social security number <#69800#><#56009#>ssc<#56009#><#69800#>, a symbol <#69801#><#56010#>anc<#56010#><#69801#>, and a <#69802#><#56011#>child<#56011#><#69802#> structure. Its effect is to modify that structure in <#69803#><#56012#>a-ft<#56012#><#69803#> whose social security number is <#69804#><#56013#>ssc<#56013#><#69804#>. If <#69805#><#56014#>anc<#56014#><#69805#> is <#69806#><#56015#>'<#56015#><#56016#>father<#56016#><#69806#>, it modifies the <#69807#><#56017#>father<#56017#><#69807#> field to contain the given <#69808#><#56018#>child<#56018#><#69808#> structure; otherwise, <#69809#><#56019#>anc<#56019#><#69809#> was the symbol <#69810#><#56020#>'<#56020#><#56021#>mother<#56021#><#69810#> and <#69811#><#56022#>add-ftn!<#56022#><#69811#> mutates the <#69812#><#56023#>mother<#56023#><#69812#> field. If the respective fields already contain a <#69813#><#56024#>child<#56024#><#69813#> structure, <#69814#><#56025#>add-ftn!<#56025#><#69814#> signals an error.

<#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.~ external Solution<#69821#><#69821#> <#56040#>Exercise 41.3.4<#56040#> Develop an implementation of a hand with <#69822#><#56042#>create-hand<#56042#><#69822#> and <#69823#><#56043#>add-at-end!<#56043#><#69823#> services using encapsulated state variables and function definitions. Use <#69824#><#56044#>set!<#56044#><#69824#> expression but no structure mutators.~ external Solution<#69825#><#69825#>
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:
  1. Recall that the first clause represents the case when <#69835#><#56105#>a-hand<#56105#><#69835#>'s <#69836#><#56106#>next<#56106#><#69836#> field is <#69837#><#56107#>empty<#56107#><#69837#>. In contrast to the situation with <#69838#><#56108#>add-at-end!<#56108#><#69838#>, it is not clear what we need to do now. According to the effect statement, we must do one of two things:
    1. If <#69839#><#56110#>a-hand<#56110#><#69839#> is the last item in a chain that consists of more than one <#69840#><#56111#>hand<#56111#><#69840#> structure, it must be removed.
    2. If <#69841#><#56112#>a-hand<#56112#><#69841#> is the only structure that <#69842#><#56113#>remove-last!<#56113#><#69842#> consumed, the function should have no effect.
    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!
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:
<#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#> #tex2html_wrap74276# <#56164#>...)<#56164#> <#56165#>...]<#56165#><#56166#>)))<#56166#> 
    <#56167#>...<#56167#> <#56168#>(rem!<#56168#> <#56169#>a-hand0<#56169#> <#56170#>...)<#56170#> <#56171#>...))<#56171#> 
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>. The <#69868#><#56228#>accumulator<#56228#><#69868#> parameter is renamed to <#69869#><#56229#>predecessor-of:a-hand<#56229#><#69869#> to emphasize the relationship to the parameter proper. The first application of <#69870#><#56230#>rem!<#56230#><#69870#> in the body of the <#56231#>local<#56231#>-expression\ hands it the second <#69871#><#56232#>hand<#56232#><#69871#> structure in <#69872#><#56233#>a-hand0<#56233#><#69872#>. The second argument is <#69873#><#56234#>a-hand0<#56234#><#69873#>, which establishes the desired relationship.
<#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:
  1. If <#69900#><#56474#>(;SPMgt;=<#56474#>\ <#56475#>(hand-rank<#56475#>\ <#56476#>a-hand)<#56476#>\ <#56477#>r<#56477#>\ <#56478#>(hand-rank<#56478#>\ <#56479#>(hand-next<#56479#>\ <#56480#>a-hand)))<#56480#><#69900#> is true, then the new card must go between the two cards that are currently linked. That is, the <#69901#><#56481#>next<#56481#><#69901#> field of <#69902#><#56482#>a-hand<#56482#><#69902#> must be changed to contain a new <#69903#><#56483#>hand<#56483#><#69903#> structure. The new structure consists of <#69904#><#56484#>r<#56484#><#69904#>, <#69905#><#56485#>s<#56485#><#69905#>, and the original value of <#69906#><#56486#>a-hand<#56486#><#69906#>'s <#69907#><#56487#>next<#56487#><#69907#> field. This yields the following elaboration of the <#69908#><#56488#>cond<#56488#>-expression<#69908#>:
    <#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#> 
    
  2. If <#69909#><#56517#>(;SPMgt;=<#56517#>\ <#56518#>(hand-rank<#56518#>\ <#56519#>a-hand)<#56519#>\ <#56520#>r<#56520#>\ <#56521#>(hand-rank<#56521#>\ <#56522#>(hand-next<#56522#>\ <#56523#>a-hand)))<#56523#><#69909#> is false, the new card must be inserted at some place in the rest of the chain. Of course, the natural recursion accomplishes just that, which finishes the analysis of the second clause of <#69910#><#56524#>sorted-insert!<#56524#><#69910#>.
Putting all the pieces together yields a partial function definition:
<#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:
  1. <#69934#><#56666#>'<#56666#><#56667#>insert<#56667#><#69934#> :: <#69935#><#56668#>rank<#56668#>\ <#56669#>suit<#56669#>\ <#56670#><#56670#><#56671#>-;SPMgt;<#56671#><#56672#><#56672#>\ <#56673#>void<#56673#><#69935#>
<#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> displays the complete function definition. It follows the pattern of section~#secencapsulate#56827>. The function itself corresponds to <#69948#><#56828#>create-hand<#56828#><#69948#>, though instead of producing a structure the new <#69949#><#56829#>create-hand<#56829#><#69949#> function produces a manager function. At this point, the manager can only deal with one message: <#69950#><#56830#>'<#56830#><#56831#>insert<#56831#><#69950#>; all other messages are rejected. An <#69951#><#56832#>'<#56832#><#56833#>insert<#56833#><#69951#> message first checks whether the new rank is larger than the first one in <#69952#><#56834#>the-hand<#56834#><#69952#>, the hidden state variable. If so, the manager just changes <#69953#><#56835#>the-hand<#56835#><#69953#>; if not, it uses <#69954#><#56836#>insert-aux!<#56836#><#69954#>, which may now assume that the new card belongs into the middle of the chain.
<#56839#>Exercise 41.3.5<#56839#> Extend the definition in figure~#fighandenc#56841> with a service for removing the first card of a given rank, even if it is the only card.~ external Solution<#69955#><#69955#> <#56847#>Exercise 41.3.6<#56847#> Extend the definition in figure~#fighandenc#56849> with a service for determing the suits of those cards in <#69956#><#56850#>the-hand<#56850#><#69956#> that have a given rank. The function should produce a list of suits.~ external Solution<#69957#><#69957#> <#56856#>Exercise 41.3.7<#56856#> Reformulate <#69958#><#56858#>create-hand<#56858#><#69958#> in figure~#fighandenc#56859> such that the manager uses a single <#69959#><#56860#>set!<#56860#>-expression<#69959#> and <#69960#><#56861#>sorted-insert<#56861#><#69960#> does not use any structure mutation.~ external Solution<#69961#><#69961#> <#56867#>Exercise 41.3.8<#56867#> Recall the definition of a binary tree from section~#secbst#56869>
A <#69962#><#56871#>binary tree<#56871#><#69962#> (<#69963#><#56872#>BT<#56872#><#69963#>) is either
  1. <#69964#><#56874#>false<#56874#><#69964#> or
  2. <#69965#><#56875#>(make-node<#56875#>\ <#56876#>soc<#56876#>\ <#56877#>pn<#56877#>\ <#56878#>lft<#56878#>\ <#56879#>rgt)<#56879#><#69965#>
    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.
where the required structure definition is
<#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.~ external 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> shows, a solution without mutators is much easier to produce than a solution based on structure mutation. And in the case of cards and hands, which deals with at most 52 structures, is equally efficient. To decide which of the two approaches to use requires a better understanding of algorithmic analysis (see intermezzo~5) and of the language mechanisms and program design recipes for encapsulating state variables.