Structures in Structures

Medical researchers rely on family trees to do research on hereditary diseases. They may, for example, search a family tree for a certain eye color. Computers can help with these tasks, so it is natural to design representations of family trees and functions for processing them. One way to maintain a family tree of a family is to add a node to the tree every time a child is born. From the node, we can draw connections to the node for the father and the one for the mother, which tells us how the people in the tree are related. For those people in the tree whose parents are unknown, we do not draw any connections. The result is a so-called ancestor tree because given any node in the tree, we can find the ancestors of that person if we follow the arrows but not the descendants. As we record a family tree, we may also want to record certain pieces of information. The birth date, birth weight, the color of the eyes, and the color of the hair are the pieces of information that we care about. Others record different information.

#picture15893#

<#15959#>Figure: A sample ancestor family tree<#15959#>


See figure~#figfamilyA#15961> for a drawing of an ancestor family tree. Adam is the child of Bettina and Carl; he has yellow eyes and was born in 1950. Similarly, Gustav is the child of Eva and Fred, has blush eyes, and was born in 1988. To represent a child in a family tree means to combine several pieces of information: information about the father, the mother, the name, the birth date, and the eye colors. This suggests that we define a new structure:
<#15966#>(define-struct<#15966#> <#15967#>child<#15967#> <#15968#>(father<#15968#> <#15969#>mother<#15969#> <#15970#>name<#15970#> <#15971#>date<#15971#> <#15972#>eyes))<#15972#>
The five fields of <#63286#><#15976#>child<#15976#><#63286#> structures record the required information, which suggests the following data definition:

#displaymath73064#

While this data definition is simple, it is unfortunately also useless. The definition refers to itself but, because it doesn't have any clauses, there is no way to create a <#63295#><#15993#>child<#15993#><#63295#> structure. If we tried to create a <#63296#><#15994#>child<#15994#><#63296#> structure, we would have to write

<#15999#>(m<#15999#><#16000#>ake-child<#16000#> 
  <#16001#>(<#16001#><#16002#>m<#16002#><#16003#>ake-child<#16003#> 
    <#16004#>(m<#16004#><#16005#>ake-child<#16005#> 
      <#16006#>(m<#16006#><#16007#>ake-child<#16007#> 
        <#16008#>...<#16008#> 
        <#16009#>)))<#16009#> 
   <#16010#>...<#16010#> <#16011#>...<#16011#> <#16012#>...<#16012#> <#16013#>...)<#16013#> 
without end. It is for this reason that we demand that all self-referential data definitions consist of several clauses (for now) and that at least one of them does not refer to the data definition. Let's postpone the data definition for a moment and let's instead study how we can use <#63297#><#16017#>child<#16017#><#63297#> structures to represent family trees. Suppose we are about to add a child to an existing family tree, and furthermore suppose that we already have representations for the parents. Then we can just construct a new <#63298#><#16018#>child<#16018#><#63298#> structure. For example, for Adam we could create the following <#63299#><#16019#>child<#16019#><#63299#> structure
<#16024#>(make-child<#16024#> <#16025#>Carl<#16025#> <#16026#>Bettina<#16026#> <#16027#>'<#16027#><#16028#>Adam<#16028#> <#16029#>1950<#16029#> <#16030#>'<#16030#><#16031#>yellow)<#16031#>
assuming <#63300#><#16035#>Carl<#16035#><#63300#> and <#63301#><#16036#>Bettina<#16036#><#63301#> stand for representations of Adam's parents. The problem is that we don't always know a person's parents. In the family depicted in figure~#figfamilyA#16037>, we don't know Bettina's parents. Yet, even if we don't know a person's father or mother, we must still use some Scheme value for the two fields in a <#63302#><#16038#>child<#16038#><#63302#> structure. We could use all kinds of values to signal a lack of information (<#63303#><#16039#>5<#16039#><#63303#>, <#63304#><#16040#>false<#16040#><#63304#>, or <#63305#><#16041#>'<#16041#><#16042#>none<#16042#><#63305#>); here, we use <#63306#><#16043#>empty<#16043#><#63306#>. For example, to construct a <#63307#><#16044#>child<#16044#><#63307#> structure for Bettina, we do the following:
<#16049#>(make-child<#16049#> <#16050#>empty<#16050#> <#16051#>empty<#16051#> <#16052#>'<#16052#><#16053#>Bettina<#16053#> <#16054#>1950<#16054#> <#16055#>'<#16055#><#16056#>green)<#16056#>
Of course, if only one of the two parents is missing, we just fill that field with <#63308#><#16060#>empty<#16060#><#63308#>. Our analysis suggests that a <#63309#><#16061#>child<#16061#><#63309#> node has the following data definition:
<#71057#>A <#16063#>child node<#16063#> is <#63310#><#16064#>(make-child<#16064#>\ <#16065#>f<#16065#>\ <#16066#>m<#16066#>\ <#16067#>na<#16067#>\ <#16068#>da<#16068#>\ <#16069#>ec)<#16069#><#63310#> where
  1. <#63311#><#16071#>f<#16071#><#63311#> and <#63312#><#16072#>m<#16072#><#63312#> are either
    1. <#63313#><#16074#>empty<#16074#><#63313#> or
    2. <#63314#><#16075#>child<#16075#><#63314#> nodes;
  2. <#63315#><#16077#>na<#16077#><#63315#> and <#63316#><#16078#>ec<#16078#><#63316#> are symbols,
  3. <#63317#><#16079#>da<#16079#><#63317#> is a number.
<#71057#>
This definition is special in two regards. First, it is a self-referential data definition involving structures. Second, the data definition mentions two alternatives for the first and second component. This violates our conventions concerning on the shape of data definitions. We can avoid this problem by defining the collection of nodes in a family tree instead:
A <#63318#><#16083#>family tree node<#16083#><#63318#> (short: <#63319#><#16084#>ftn<#16084#><#63319#>) is either
  1. <#63320#><#16086#>empty<#16086#><#63320#>, or
  2. <#63321#><#16087#>(make-child<#16087#>\ <#16088#>f<#16088#>\ <#16089#>m<#16089#>\ <#16090#>na<#16090#>\ <#16091#>da<#16091#>\ <#16092#>ec)<#16092#><#63321#>
    where <#63322#><#16093#>f<#16093#><#63322#> and <#63323#><#16094#>m<#16094#><#63323#> are <#16095#>ftn<#16095#>s, <#63324#><#16096#>na<#16096#><#63324#>
    and <#63325#><#16097#>ec<#16097#><#63325#> are symbols, and <#16098#>da<#16098#> is a number.
This new definition satisfies our conventions. It consists of two clauses. One of the clauses is self-referential, the other is not. In contrast to previous data definitions involving structures, the definition of <#63326#><#16101#>ftn<#16101#><#63326#> is not a plain explanation of what kind of data can show up in which field. Instead, it is multi-clausal and self-referential. Considering that this is the first such data definition, let us carefully translate the example from figure~#figfamilyA#16102> and thus reassure ourselves that the new class of data can represent the information of interest.
<#16107#>;; Oldest Generation:<#16107#>
<#16108#>(define<#16108#> <#16109#>Carl<#16109#> <#16110#>(make-child<#16110#> <#16111#>empty<#16111#> <#16112#>empty<#16112#> <#16113#>'<#16113#><#16114#>Carl<#16114#> <#16115#>1926<#16115#> <#16116#>'<#16116#><#16117#>green))<#16117#> 
<#16118#>(define<#16118#> <#16119#>Bettina<#16119#> <#16120#>(make-child<#16120#> <#16121#>empty<#16121#> <#16122#>empty<#16122#> <#16123#>'<#16123#><#16124#>Bettina<#16124#> <#16125#>1926<#16125#> <#16126#>'<#16126#><#16127#>green))<#16127#> 
<#16128#>;; Middle Generation:<#16128#> 
<#16129#>(define<#16129#> <#16130#>Adam<#16130#> <#16131#>(make-child<#16131#> <#16132#>Carl<#16132#> <#16133#>Bettina<#16133#> <#16134#>'<#16134#><#16135#>Adam<#16135#> <#16136#>1950<#16136#> <#16137#>'<#16137#><#16138#>yellow))<#16138#> 
<#16139#>(define<#16139#> <#16140#>Dave<#16140#> <#16141#>(make-child<#16141#> <#16142#>Carl<#16142#> <#16143#>Bettina<#16143#> <#16144#>'<#16144#><#16145#>Dave<#16145#> <#16146#>1955<#16146#> <#16147#>'<#16147#><#16148#>black))<#16148#> 
<#16149#>(define<#16149#> <#16150#>Eva<#16150#> <#16151#>(make-child<#16151#> <#16152#>Carl<#16152#> <#16153#>Bettina<#16153#> <#16154#>'<#16154#><#16155#>Eva<#16155#> <#16156#>1965<#16156#> <#16157#>'<#16157#><#16158#>blue))<#16158#> 
<#16159#>(define<#16159#> <#16160#>Fred<#16160#> <#16161#>(make-child<#16161#> <#16162#>empty<#16162#> <#16163#>empty<#16163#> <#16164#>'<#16164#><#16165#>Fred<#16165#> <#16166#>1966<#16166#> <#16167#>'<#16167#><#16168#>pink))<#16168#> 
<#16169#>;; Youngest Generation: <#16169#> 
<#16170#>(define<#16170#> <#16171#>Gustav<#16171#> <#16172#>(make-child<#16172#> <#16173#>Fred<#16173#> <#16174#>Eva<#16174#> <#16175#>'<#16175#><#16176#>Gustav<#16176#> <#16177#>1988<#16177#> <#16178#>'<#16178#><#16179#>blush))<#16179#> 
<#16183#>Figure: A Scheme representation of the sample family tree<#16183#>
The information for Carl is easy to translate into a <#63327#><#16185#>ftn<#16185#><#63327#>:
<#16190#>(make-child<#16190#> <#16191#>empty<#16191#> <#16192#>empty<#16192#> <#16193#>'<#16193#><#16194#>Carl<#16194#> <#16195#>1926<#16195#> <#16196#>'<#16196#><#16197#>green)<#16197#>
Bettina and Fred are represented with similar nodes. Accordingly, the node for Adam is created with
<#16205#>(make-child<#16205#> <#16206#>(make-child<#16206#> <#16207#>empty<#16207#> <#16208#>empty<#16208#> <#16209#>'<#16209#><#16210#>Carl<#16210#> <#16211#>1926<#16211#> <#16212#>'<#16212#><#16213#>green)<#16213#> 
            <#16214#>(make-child<#16214#> <#16215#>empty<#16215#> <#16216#>empty<#16216#> <#16217#>'<#16217#><#16218#>Bettina<#16218#> <#16219#>1950<#16219#> <#16220#>'<#16220#><#16221#>green)<#16221#> 
            <#16222#>'<#16222#><#16223#>Adam<#16223#> 
            <#16224#>1950<#16224#> 
            <#16225#>'<#16225#><#16226#>yellow)<#16226#> 
As the examples show, a simple-minded, node-by-node transliteration of figure~#figfamilyA#16230> requires numerous repetitions of data. For example, if we constructed the <#63328#><#16231#>child<#16231#><#63328#> structure for Dave like the one for Adam, we would get
<#16236#>(make-child<#16236#> <#16237#>(make-child<#16237#> <#16238#>empty<#16238#> <#16239#>empty<#16239#> <#16240#>'<#16240#><#16241#>Carl<#16241#> <#16242#>1926<#16242#> <#16243#>'<#16243#><#16244#>green)<#16244#> 
            <#16245#>(make-child<#16245#> <#16246#>empty<#16246#> <#16247#>empty<#16247#> <#16248#>'<#16248#><#16249#>Bettina<#16249#> <#16250#>1950<#16250#> <#16251#>'<#16251#><#16252#>green)<#16252#> 
            <#16253#>'<#16253#><#16254#>Dave<#16254#> 
            <#16255#>1955<#16255#> 
            <#16256#>'<#16256#><#16257#>black)<#16257#> 
Hence, it is a good idea to introduce a variable definition per node and to use the variable thereafter. To make things easy, we use <#63329#><#16261#>Carl<#16261#><#63329#> to stand for the <#63330#><#16262#>child<#16262#><#63330#> structure that describes Carl, and so on. The complete transliteration of the family tree into Scheme can be found in figure~#figfamilyS#16263>. The structure definitions in figure~#figfamilyS#16264> naturally correspond to an image of deeply nested boxes. Each box has five compartments. The first two contain boxes again, which in turn contain boxes in their first two compartments and so on. Thus, if we were to draw the structure definitions for the family tree using nested boxes, we would quickly be overwhelmed by the details of the picture. Furthermore, the picture would copy certain portions of the tree just like our attempt to use <#63331#><#16265#>make-child<#16265#><#63331#> without variable definitions. For these reasons, it is better to imagine the structures as boxes and arrows, as originally drawn in figure~#figfamilyA#16266>. In general, a programmer must flexibly switch back and forth between both of these graphical illustrations. For extracting values from structures, the boxes-in-boxes image works best; for finding our way around large collections of interconnected structures, the boxes-and-arrows image works better. Equipped with a firm understanding of the family tree representation, we can turn to the design of functions that consume family trees. Let us first look at a generic function of this kind:
<#71058#>;; <#63332#><#16271#>fun-for-ftn<#16271#> <#16272#>:<#16272#> <#16273#>ftn<#16273#> <#16274#><#16274#><#16275#>-;SPMgt;<#16275#><#16276#><#16276#> <#16277#>?<#16277#><#16278#>?<#16278#><#16279#>?<#16279#><#63332#><#71058#>
<#16280#>(define<#16280#> <#16281#>(fun-for-ftn<#16281#> <#16282#>a-ftree)<#16282#> <#16283#>...)<#16283#> 
After all, we should be able to construct the template without considering the purpose of a function. Since the data definition for <#63333#><#16287#>ftn<#16287#><#63333#>s contains two clauses, the template must consist of a <#63334#><#16288#>cond<#16288#>-expression<#63334#> with two clauses. The first deals with <#63335#><#16289#>empty<#16289#><#63335#>, the second one with <#63336#><#16290#>child<#16290#><#63336#> structures:
<#71059#>;; <#63337#><#16295#>fun-for-ftn<#16295#> <#16296#>:<#16296#> <#16297#>ftn<#16297#> <#16298#><#16298#><#16299#>-;SPMgt;<#16299#><#16300#><#16300#> <#16301#>?<#16301#><#16302#>?<#16302#><#16303#>?<#16303#><#63337#><#71059#>
<#16304#>(d<#16304#><#16305#>efine<#16305#> <#16306#>(fun-for-ftn<#16306#> <#16307#>a-ftree)<#16307#> 
  <#16308#>(c<#16308#><#16309#>ond<#16309#> 
    <#16310#>[<#16310#><#16311#>(empty?<#16311#> <#16312#>a-ftree)<#16312#> <#16313#>...]<#16313#> 
    <#16314#>[<#16314#><#16315#>e<#16315#><#16316#>lse<#16316#> <#71060#>; <#63338#><#16317#>(child?<#16317#> <#16318#>a-ftree)<#16318#><#63338#><#71060#> 
      <#16319#>...<#16319#> <#16320#>]<#16320#><#16321#>))<#16321#> 
Furthermore, for the first clause, the input is atomic so there is nothing further to be done. For the second clause, though, the input contains five pieces of information: two other family tree nodes, the person's name, birth date, and eye color:
<#71061#>;; <#63339#><#16329#>fun-for-ftn<#16329#> <#16330#>:<#16330#> <#16331#>ftn<#16331#> <#16332#><#16332#><#16333#>-;SPMgt;<#16333#><#16334#><#16334#> <#16335#>?<#16335#><#16336#>?<#16336#><#16337#>?<#16337#><#63339#><#71061#>
<#16338#>(d<#16338#><#16339#>efine<#16339#> <#16340#>(fun-for-ftn<#16340#> <#16341#>a-ftree)<#16341#> 
  <#16342#>(c<#16342#><#16343#>ond<#16343#> 
    <#16344#>[<#16344#><#16345#>(empty?<#16345#> <#16346#>a-ftree)<#16346#> <#16347#>...]<#16347#> 
    <#16348#>[<#16348#><#16349#>e<#16349#><#16350#>lse<#16350#> 
      <#16351#>...<#16351#> <#16352#>(fun-for-ftn<#16352#> <#16353#>(child-father<#16353#> <#16354#>a-ftree))<#16354#> <#16355#>...<#16355#> 
      <#16356#>...<#16356#> <#16357#>(fun-for-ftn<#16357#> <#16358#>(child-mother<#16358#> <#16359#>a-ftree))<#16359#> <#16360#>...<#16360#> 
      <#16361#>...<#16361#> <#16362#>(child-name<#16362#> <#16363#>a-ftree)<#16363#> <#16364#>...<#16364#> 
      <#16365#>...<#16365#> <#16366#>(child-date<#16366#> <#16367#>a-ftree)<#16367#> <#16368#>...<#16368#> 
      <#16369#>...<#16369#> <#16370#>(child-eyes<#16370#> <#16371#>a-ftree)<#16371#> <#16372#>...]<#16372#><#16373#>))<#16373#> 
We also apply <#63340#><#16377#>fun-for-ftn<#16377#><#63340#> to the <#63341#><#16378#>father<#16378#><#63341#> and <#63342#><#16379#>mother<#16379#><#63342#> fields because of the self-references in the second clause of the data definition. Let us now turn to a concrete example: <#63343#><#16380#>blue-eyed-ancestor?<#16380#><#63343#>, the function that determines whether anyone in some given family tree has blue eyes:
<#71062#>;; <#63344#><#16385#>blue-eyed-ancestor?<#16385#> <#16386#>:<#16386#> <#16387#>ftn<#16387#> <#16388#><#16388#><#16389#>-;SPMgt;<#16389#><#16390#><#16390#> <#16391#>boolean<#16391#><#63344#><#71062#>
<#71063#>;; to determine whether <#63345#><#16392#>a-ftree<#16392#><#63345#> contains a <#63346#><#16393#>child<#16393#><#63346#><#71063#> 
<#71064#>;; structure with <#63347#><#16394#>'<#16394#><#16395#>blue<#16395#><#63347#> in the <#63348#><#16396#>eyes<#16396#><#63348#> field<#71064#> 
<#16397#>(define<#16397#> <#16398#>(blue-eyed-ancestor?<#16398#> <#16399#>a-ftree)<#16399#> <#16400#>...)<#16400#> 
Following our recipe, we first develop some examples. Consider the family tree node for Carl. He does not have blue eyes, and because he doesn't have any (known) ancestors in our family tree, the family tree represented by this node does not contain a person with blue eyes. In short,
  <#16408#>(blue-eyed-ancestor?<#16408#> <#16409#>Carl)<#16409#>
<#16410#>=<#16410#> <#16411#>false<#16411#> 
In contrast, the family tree represented by <#63349#><#16415#>Gustav<#16415#><#63349#> contains a node for Eva who does have blue eyes. Hence,
  <#16420#>(blue-eyed-ancestor?<#16420#> <#16421#>Gustav)<#16421#>
<#16422#>=<#16422#> <#16423#>true<#16423#> 
The function template is like that of <#63350#><#16427#>fun-for-ftn<#16427#><#63350#>, except that we use the name <#63351#><#16428#>blue-eyed-ancestor?<#16428#><#63351#>. As always, we use the template to guide the function design. First we assume that <#63352#><#16429#>(empty?<#16429#>\ <#16430#>a-ftree)<#16430#><#63352#> holds. In that case, the family tree is empty, and nobody has blue eyes. Hence, the answer must be <#63353#><#16431#>false<#16431#><#63353#>. The second clause of the template contains several expressions, which we must interpret:
  1. <#63354#><#16433#>(blue-eyed-ancestor?<#16433#>\ <#16434#>(child-father<#16434#>\ <#16435#>a-ftree))<#16435#><#63354#>, which determines whether someone in the father's <#63355#><#16436#>ftn<#16436#><#63355#> has blue eyes;
  2. <#63356#><#16437#>(blue-eyed-ancestor?<#16437#>\ <#16438#>(child-mother<#16438#>\ <#16439#>a-ftree))<#16439#><#63356#>, which determines whether someone in the mother's <#63357#><#16440#>ftn<#16440#><#63357#> has blue eyes;
  3. <#63358#><#16441#>(child-name<#16441#>\ <#16442#>a-ftree)<#16442#><#63358#>, which extracts the <#63359#><#16443#>child<#16443#><#63359#>'s name;
  4. <#63360#><#16444#>(child-date<#16444#>\ <#16445#>a-ftree)<#16445#><#63360#>, which extracts the <#63361#><#16446#>child<#16446#><#63361#>'s date of birth; and
  5. <#63362#><#16447#>(child-eyes<#16447#>\ <#16448#>a-ftree)<#16448#><#63362#>, which extracts the <#63363#><#16449#>child<#16449#><#63363#>'s eye colors.
It is now up to us to use these values properly. Clearly, if the <#63364#><#16451#>child<#16451#><#63364#> structure contains <#63365#><#16452#>'<#16452#><#16453#>blue<#16453#><#63365#> in the <#63366#><#16454#>eyes<#16454#><#63366#> field, the function's answer is <#63367#><#16455#>true<#16455#><#63367#>. Otherwise, the function produces <#63368#><#16456#>true<#16456#><#63368#> if there is a blue-eyed person in either the father's or the mother's family tree. The rest of the data is useless. Our discussion suggests that we formulate a conditional expression and that the first condition is
<#16461#>(symbol=?<#16461#> <#16462#>(child-eyes<#16462#> <#16463#>a-ftree)<#16463#> <#16464#>'<#16464#><#16465#>blue)<#16465#>
The two recursions are the other two conditions. If either one produces <#63369#><#16469#>true<#16469#><#63369#>, the function produces <#63370#><#16470#>true<#16470#><#63370#>. The <#63371#><#16471#>else<#16471#><#63371#>-clause produces <#63372#><#16472#>false<#16472#><#63372#>. In summary, the answer in the second clause is the following expression:
<#16477#>(c<#16477#><#16478#>ond<#16478#>
  <#16479#>[<#16479#><#16480#>(symbol=?<#16480#> <#16481#>(child-eyes<#16481#> <#16482#>a-ftree)<#16482#> <#16483#>'<#16483#><#16484#>blue)<#16484#> <#16485#>true<#16485#><#16486#>]<#16486#> 
  <#16487#>[<#16487#><#16488#>(blue-eyed-ancestor?<#16488#> <#16489#>(child-father<#16489#> <#16490#>a-ftree))<#16490#> <#16491#>true<#16491#><#16492#>]<#16492#> 
  <#16493#>[<#16493#><#16494#>(blue-eyed-ancestor?<#16494#> <#16495#>(child-mother<#16495#> <#16496#>a-ftree))<#16496#> <#16497#>true<#16497#><#16498#>]<#16498#> 
  <#16499#>[<#16499#><#16500#>else<#16500#> <#16501#>false<#16501#><#16502#>]<#16502#><#16503#>)<#16503#> 
The first definition in figure~#figblueeyes#16507> pulls everything together. The second definition shows how to formulate this <#63373#><#16508#>cond<#16508#>-expression<#63373#> as an equivalent <#63374#><#16509#>or<#16509#>-expression<#63374#>, testing one condition after the next, until one of them is <#63375#><#16510#>true<#16510#><#63375#> or all of them have evaluated to <#63376#><#16511#>false<#16511#><#63376#>. The function <#63377#><#16512#>blue-eyed-ancestor?<#16512#><#63377#> is unusual in that it uses the recursions as conditions in a <#63378#><#16513#>cond<#16513#>-expression<#63378#>s. To understand how this works, let us evaluate an application of <#63379#><#16514#>blue-eyed-ancestor?<#16514#><#63379#> to <#63380#><#16515#>Carl<#16515#><#63380#> by hand:
  <#16520#>(blue-eyed-ancestor?<#16520#> <#16521#>Carl)<#16521#>
<#16522#>=<#16522#> <#16523#>(blue-eyed-ancestor?<#16523#> <#16524#>(make-child<#16524#> <#16525#>empty<#16525#> <#16526#>empty<#16526#> <#16527#>'<#16527#><#16528#>Carl<#16528#> <#16529#>1926<#16529#> <#16530#>'<#16530#><#16531#>green))<#16531#> 
<#16532#>=<#16532#> <#16533#>(c<#16533#><#16534#>ond<#16534#> 
    <#16535#>[<#16535#><#16536#>(empty?<#16536#> <#16537#>(make-child<#16537#> <#16538#>empty<#16538#> <#16539#>empty<#16539#> <#16540#>'<#16540#><#16541#>Carl<#16541#> <#16542#>1926<#16542#> <#16543#>'<#16543#><#16544#>green))<#16544#> <#16545#>false<#16545#><#16546#>]<#16546#> 
    <#16547#>[<#16547#><#16548#>e<#16548#><#16549#>lse<#16549#> 
      <#16550#>(c<#16550#><#16551#>ond<#16551#> 
        <#16552#>[<#16552#><#16553#>(s<#16553#><#16554#>ymbol=?<#16554#> 
           <#16555#>(child-eyes<#16555#> <#16556#>(make-child<#16556#> <#16557#>empty<#16557#> <#16558#>empty<#16558#> <#16559#>'<#16559#><#16560#>Carl<#16560#> <#16561#>1926<#16561#> <#16562#>'<#16562#><#16563#>green))<#16563#> 
           <#16564#>'<#16564#><#16565#>blue)<#16565#> 
         <#16566#>true<#16566#><#16567#>]<#16567#> 
        <#16568#>[<#16568#><#16569#>(b<#16569#><#16570#>lue-eyed-ancestor?<#16570#> 
           <#16571#>(child-father<#16571#> <#16572#>(make-child<#16572#> <#16573#>empty<#16573#> <#16574#>empty<#16574#> <#16575#>'<#16575#><#16576#>Carl<#16576#> <#16577#>1926<#16577#> <#16578#>'<#16578#><#16579#>green)))<#16579#> 
         <#16580#>true<#16580#><#16581#>]<#16581#> 
        <#16582#>[<#16582#><#16583#>(b<#16583#><#16584#>lue-eyed-ancestor?<#16584#> 
           <#16585#>(child-mother<#16585#> <#16586#>(make-child<#16586#> <#16587#>empty<#16587#> <#16588#>empty<#16588#> <#16589#>'<#16589#><#16590#>Carl<#16590#> <#16591#>1926<#16591#> <#16592#>'<#16592#><#16593#>green)))<#16593#> 
         <#16594#>true<#16594#><#16595#>]<#16595#> 
        <#16596#>[<#16596#><#16597#>else<#16597#> <#16598#>false<#16598#><#16599#>]<#16599#><#16600#>)]<#16600#><#16601#>)<#16601#> 
<#16602#>=<#16602#> <#16603#>(c<#16603#><#16604#>ond<#16604#> 
    <#16605#>[<#16605#><#16606#>(symbol=?<#16606#> <#16607#>'<#16607#><#16608#>green<#16608#> <#16609#>'<#16609#><#16610#>blue)<#16610#> <#16611#>true<#16611#><#16612#>]<#16612#> 
    <#16613#>[<#16613#><#16614#>(blue-eyed-ancestor?<#16614#> <#16615#>empty)<#16615#> <#16616#>true<#16616#><#16617#>]<#16617#> 
    <#16618#>[<#16618#><#16619#>(blue-eyed-ancestor?<#16619#> <#16620#>empty)<#16620#> <#16621#>true<#16621#><#16622#>]<#16622#> 
    <#16623#>[<#16623#><#16624#>else<#16624#> <#16625#>false<#16625#><#16626#>]<#16626#><#16627#>)<#16627#> 
<#16628#>=<#16628#> <#16629#>(c<#16629#><#16630#>ond<#16630#> 
    <#16631#>[<#16631#><#16632#>false<#16632#> <#16633#>true<#16633#><#16634#>]<#16634#> 
    <#16635#>[<#16635#><#16636#>false<#16636#> <#16637#>true<#16637#><#16638#>]<#16638#> 
    <#16639#>[<#16639#><#16640#>false<#16640#> <#16641#>true<#16641#><#16642#>]<#16642#> 
    <#16643#>[<#16643#><#16644#>else<#16644#> <#16645#>false<#16645#><#16646#>]<#16646#><#16647#>)<#16647#> 
<#16648#>=<#16648#> <#16649#>false<#16649#> 
The evaluation confirms that <#63381#><#16653#>blue-eyed-ancestor?<#16653#><#63381#> works properly for <#63382#><#16654#>Carl<#16654#><#63382#>, and it also illustrates how the function works.
<#71065#>;; <#63383#><#16659#>blue-eyed-ancestor?<#16659#> <#16660#>:<#16660#> <#16661#>ftn<#16661#> <#16662#><#16662#><#16663#>-;SPMgt;<#16663#><#16664#><#16664#> <#16665#>boolean<#16665#><#63383#><#71065#>
<#71066#>;; to determine whether <#63384#><#16666#>a-ftree<#16666#><#63384#> contains a <#63385#><#16667#>child<#16667#><#63385#><#71066#> 
<#71067#>;; structure with <#63386#><#16668#>'<#16668#><#16669#>blue<#16669#><#63386#> in the <#63387#><#16670#>eyes<#16670#><#63387#> field<#71067#> 
<#71068#>;; version 1: using a nested <#63388#><#16671#>cond<#16671#>-expression<#63388#><#71068#> 
<#16672#>(d<#16672#><#16673#>efine<#16673#> <#16674#>(blue-eyed-ancestor?<#16674#> <#16675#>a-ftree)<#16675#> 
  <#16676#>(c<#16676#><#16677#>ond<#16677#> 
    <#16678#>[<#16678#><#16679#>(empty?<#16679#> <#16680#>a-ftree)<#16680#> <#16681#>false<#16681#><#16682#>]<#16682#> 
    <#16683#>[<#16683#><#16684#>else<#16684#> <#16685#>(c<#16685#><#16686#>ond<#16686#> 
            <#16687#>[<#16687#><#16688#>(symbol=?<#16688#> <#16689#>(child-eyes<#16689#> <#16690#>a-ftree)<#16690#> <#16691#>'<#16691#><#16692#>blue)<#16692#> <#16693#>true<#16693#><#16694#>]<#16694#> 
            <#16695#>[<#16695#><#16696#>(blue-eyed-ancestor?<#16696#> <#16697#>(child-father<#16697#> <#16698#>a-ftree))<#16698#> <#16699#>true<#16699#><#16700#>]<#16700#> 
            <#16701#>[<#16701#><#16702#>(blue-eyed-ancestor?<#16702#> <#16703#>(child-mother<#16703#> <#16704#>a-ftree))<#16704#> <#16705#>true<#16705#><#16706#>]<#16706#> 
            <#16707#>[<#16707#><#16708#>else<#16708#> <#16709#>false<#16709#><#16710#>]<#16710#><#16711#>)]<#16711#><#16712#>))<#16712#> 
<#71069#>;; <#63389#><#16720#>blue-eyed-ancestor?<#16720#> <#16721#>:<#16721#> <#16722#>ftn<#16722#> <#16723#><#16723#><#16724#>-;SPMgt;<#16724#><#16725#><#16725#> <#16726#>boolean<#16726#><#63389#><#71069#>
<#71070#>;; to determine whether <#63390#><#16727#>a-ftree<#16727#><#63390#> contains a <#63391#><#16728#>child<#16728#><#63391#><#71070#> 
<#71071#>;; structure with <#63392#><#16729#>'<#16729#><#16730#>blue<#16730#><#63392#> in the <#63393#><#16731#>eyes<#16731#><#63393#> field<#71071#> 
<#71072#>;; version 2: using an <#63394#><#16732#>or<#16732#>-expression<#63394#><#71072#> 
<#16733#>(d<#16733#><#16734#>efine<#16734#> <#16735#>(blue-eyed-ancestor?<#16735#> <#16736#>a-ftree)<#16736#> 
  <#16737#>(c<#16737#><#16738#>ond<#16738#> 
    <#16739#>[<#16739#><#16740#>(empty?<#16740#> <#16741#>a-ftree)<#16741#> <#16742#>false<#16742#><#16743#>]<#16743#> 
    <#16744#>[<#16744#><#16745#>else<#16745#> <#16746#>(or<#16746#> <#16747#>(symbol=?<#16747#> <#16748#>(child-eyes<#16748#> <#16749#>a-ftree)<#16749#> <#16750#>'<#16750#><#16751#>blue)<#16751#> 
              <#16752#>(or<#16752#> <#16753#>(blue-eyed-ancestor?<#16753#> <#16754#>(child-father<#16754#> <#16755#>a-ftree))<#16755#> 
                  <#16756#>(blue-eyed-ancestor?<#16756#> <#16757#>(child-mother<#16757#> <#16758#>a-ftree))))]<#16758#><#16759#>))<#16759#> 
<#16763#>Figure: Two functions for finding a blue-eyed ancestor<#16763#>

<#16767#>Exercise 14.1.1<#16767#> The second definition of <#63395#><#16769#>blue-eyed-ancestor?<#16769#><#63395#> in figure~#figblueeyes#16770> uses an <#63396#><#16771#>or<#16771#>-expression<#63396#> instead of a nested conditional. Use a hand-evaluation to show that this definition produces the same output for the inputs <#63397#><#16772#>empty<#16772#><#63397#> and <#63398#><#16773#>Carl<#16773#><#63398#>.~ external Solution<#63399#><#63399#> <#16779#>Exercise 14.1.2<#16779#> Confirm that
<#16785#>(blue-eyed-ancestor?<#16785#> <#16786#>empty)<#16786#> <#16787#>=<#16787#> <#16788#>false<#16788#> 
with a hand-evaluation. Evaluate <#63400#><#16792#>(blue-eyed-ancestor?<#16792#>\ <#16793#>Gustav)<#16793#><#63400#> by hand and with DrScheme. For the hand-evaluation, skip those steps in the evaluation that concern extractions, comparisons, and conditions involving <#63401#><#16794#>empty?<#16794#><#63401#>. Also reuse established equations where possible, especially the one above.~ external Solution<#63402#><#63402#> <#16800#>Exercise 14.1.3<#16800#> Develop <#63403#><#16802#>count-persons<#16802#><#63403#>. The function consumes a family tree node and produces the number of people in the corresponding family tree.~ external Solution<#63404#><#63404#> <#16808#>Exercise 14.1.4<#16808#> Develop the function <#63405#><#16810#>average-age<#16810#><#63405#>. It consumes a family tree node and the current year. It produces the average age of all people in the family tree.~ external Solution<#63406#><#63406#> <#16816#>Exercise 14.1.5<#16816#> Develop the function <#63407#><#16818#>eye-colors<#16818#><#63407#>, which consumes a family tree node and produces a list of all eye colors in the tree. An eye color may occur more than once in the list. <#16819#>Hint:<#16819#> \ Use the Scheme operation <#63408#><#16820#>append<#16820#><#63408#>, which consumes two lists and produces the concatenation of the two lists:
  <#16825#>(append<#16825#> <#16826#>(list<#16826#> <#16827#>'<#16827#><#16828#>a<#16828#> <#16829#>'<#16829#><#16830#>b<#16830#> <#16831#>'<#16831#><#16832#>c)<#16832#> <#16833#>(list<#16833#> <#16834#>'<#16834#><#16835#>d<#16835#> <#16836#>'<#16836#><#16837#>e))<#16837#> 
<#16838#>=<#16838#> <#16839#>(list<#16839#> <#16840#>'<#16840#><#16841#>a<#16841#> <#16842#>'<#16842#><#16843#>b<#16843#> <#16844#>'<#16844#><#16845#>c<#16845#> <#16846#>'<#16846#><#16847#>d<#16847#> <#16848#>'<#16848#><#16849#>e)<#16849#> 
We discuss the development of functions like <#63409#><#16853#>append<#16853#><#63409#> in section~#secsimu#16854>.~ external Solution<#63410#><#63410#> <#16860#>Exercise 14.1.6<#16860#> Suppose we need the function <#63411#><#16862#>proper-blue-eyed-ancestor?<#16862#><#63411#>. It is like <#63412#><#16863#>blue-eyed-ancestor?<#16863#><#63412#> but only responds with <#63413#><#16864#>true<#16864#><#63413#> when some proper ancestor, not the given one, has blue eyes. The contract for this new function is basically the same as for the old one:
<#71073#>;; <#63414#><#16869#>proper-blue-eyed-ancestor?<#16869#> <#16870#>:<#16870#> <#16871#>ftn<#16871#> <#16872#><#16872#><#16873#>-;SPMgt;<#16873#><#16874#><#16874#> <#16875#>boolean<#16875#><#63414#><#71073#>
<#71074#>;; to determine whether <#63415#><#16876#>a-ftree<#16876#><#63415#> has a blue-eyed ancestor<#71074#> 
<#16877#>(define<#16877#> <#16878#>(proper-blue-eyed-ancestor?<#16878#> <#16879#>a-ftree)<#16879#> <#16880#>...)<#16880#> 
To appreciate the difference, we need to look at Eva, who is blue-eyed, but does not have a blue-eyed ancestor. Hence,
  <#16888#>(blue-eyed-ancestor?<#16888#> <#16889#>Eva)<#16889#>
<#16890#>=<#16890#> <#16891#>true<#16891#> 
but
  <#16899#>(proper-blue-eyed-ancestor?<#16899#> <#16900#>Eva)<#16900#>
<#16901#>=<#16901#> <#16902#>false<#16902#> 
After all <#63416#><#16906#>Eva<#16906#><#63416#> is not a proper ancestor of herself. Suppose a friend sees the purpose statement and comes up with this solution:
<#16911#>(d<#16911#><#16912#>efine<#16912#> <#16913#>(proper-blue-eyed-ancestor?<#16913#> <#16914#>a-ftree)<#16914#>
  <#16915#>(c<#16915#><#16916#>ond<#16916#> 
    <#16917#>[<#16917#><#16918#>(empty?<#16918#> <#16919#>a-ftree)<#16919#> <#16920#>false<#16920#><#16921#>]<#16921#> 
    <#16922#>[<#16922#><#16923#>else<#16923#> <#16924#>(or<#16924#> <#16925#>(proper-blue-eyed-ancestor?<#16925#> <#16926#>(child-father<#16926#> <#16927#>a-ftree))<#16927#> 
              <#16928#>(proper-blue-eyed-ancestor?<#16928#> <#16929#>(child-mother<#16929#> <#16930#>a-ftree)))]<#16930#><#16931#>))<#16931#> 
What would be the result of <#63417#><#16935#>(proper-blue-eyed-ancestor?<#16935#>\ <#16936#>A)<#16936#><#63417#> for <#16937#>any<#16937#> <#63418#><#16938#>ftn<#16938#><#63418#> <#63419#><#16939#>A<#16939#><#63419#>? Fix the friend's solution.~ external Solution<#63420#><#63420#>