1934 lines
1 MiB
HTML
1934 lines
1 MiB
HTML
|
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||
|
<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"/><meta name="viewport" content="width=device-width, initial-scale=0.8"/><title>IV Intertwined Data</title><link rel="stylesheet" type="text/css" href="scribble.css" title="default"/><link rel="stylesheet" type="text/css" href="shared.css" title="default"/><link rel="stylesheet" type="text/css" href="figure.css" title="default"/><link rel="stylesheet" type="text/css" href="racket.css" title="default"/><link rel="stylesheet" type="text/css" href="manual-style.css" title="default"/><link rel="stylesheet" type="text/css" href="manual-racket.css" title="default"/><script type="text/javascript" src="scribble-common.js"></script><script type="text/javascript" src="figure.js"></script><script type="text/javascript" src="manual-racket.js"></script><!--[if IE 6]><style type="text/css">.SIEHidden { overflow: hidden; }</style><![endif]--></head><body id="scribble-racket-lang-org"><div class="tocset"><div class="tocview"><div class="tocviewlist tocviewlisttopspace"><div class="tocviewtitle"><table cellspacing="0" cellpadding="0"><tr><td style="width: 1em;"><a href="javascript:void(0);" title="Expand/Collapse" class="tocviewtoggle" onclick="TocviewToggle(this,"tocview_0");">▼</a></td><td></td><td><a href="index.html" class="tocviewlink" data-pltdoc="x">How to Design Programs, Second Edition</a></td></tr></table></div><div class="tocviewsublisttop" style="display: block;" id="tocview_0"><table cellspacing="0" cellpadding="0"><tr><td align="right"></td><td><a href="part_preface.html" class="tocviewlink" data-pltdoc="x">Preface</a></td></tr><tr><td align="right"></td><td><a href="part_prologue.html" class="tocviewlink" data-pltdoc="x">Prologue:<span class="mywbr"> </span> How to Program</a></td></tr><tr><td align="right">I </td><td><a href="part_one.html" class="tocviewlink" data-pltdoc="x">Fixed-<wbr></wbr>Size Data</a></td></tr><tr><td align="right"></td><td><a href="i1-2.html" class="tocviewlink" data-pltdoc="x">Intermezzo 1: Beginning Student Language</a></td></tr><tr><td align="right">II </td><td><a href="part_two.html" class="tocviewlink" data-pltdoc="x">Arbitrarily Large Data</a></td></tr><tr><td align="right"></td><td><a href="i2-3.html" class="tocviewlink" data-pltdoc="x">Intermezzo 2: Quote, Unquote</a></td></tr><tr><td align="right">III </td><td><a href="part_three.html" class="tocviewlink" data-pltdoc="x">Abstraction</a></td></tr><tr><td align="right"></td><td><a href="i3-4.html" class="tocviewlink" data-pltdoc="x">Intermezzo 3: Scope and Abstraction</a></td></tr><tr><td align="right">IV </td><td><a href="part_four.html" class="tocviewselflink" data-pltdoc="x">Intertwined Data</a></td></tr><tr><td align="right"></td><td><a href="i4-5.html" class="tocviewlink" data-pltdoc="x">Intermezzo 4: The Nature of Numbers</a></td></tr><tr><td align="right">V </td><td><a href="part_five.html" class="tocviewlink" data-pltdoc="x">Generative Recursion</a></td></tr><tr><td align="right"></td><td><a href="i5-6.html" class="tocviewlink" data-pltdoc="x">Intermezzo 5: The Cost of Computation</a></td></tr><tr><td align="right">VI </td><td><a href="part_six.html" class="tocviewlink" data-pltdoc="x">Accumulators</a></td></tr><tr><td align="right"></td><td><a href="part_epilogue.html" class="tocviewlink" data-pltdoc="x">Epilogue:<span class="mywbr"> </span> Moving On</a></td></tr></table></div></div><div class="tocviewlist"><table cellspacing="0" cellpadding="0"><tr><td style="width: 1em;"><a href="javascript:void(0);" title="Expand/Collapse" class="tocviewtoggle" onclick="TocviewToggle(this,"tocview_1");">►</a></td><td>IV </td><td><a href="part_four.html" class="tocviewselflink" data-pltdoc="x">Intertwined Data</a></td></tr></table><div class="tocviewsublistbottom" style="display: none;" id="tocview_1"><table cellspacing="0" cellpadding="0"><tr><td align="right">19 </td><td><a href="part_four.html#%28part._ch~3apoetry-sexp%29" class="tocviewlink" data-pltdoc="x">The Poetry of S-<wbr>
|
||
|
quite unusual. These data definitions refer to themselves, and in all
|
||
|
likelihood they are the first such definitions you have ever
|
||
|
encountered. As it turns out, many classes of data require even more
|
||
|
complex data definitions than these two. Common generalizations involve
|
||
|
many self-references in one data definition or a bunch of data definitions
|
||
|
that refer to each other. These forms of data have become ubiquitous, and
|
||
|
it is therefore critical for a programmer to learn to cope with <span style="font-weight: bold">any</span>
|
||
|
collection of data definitions. And that’s what the design recipe is all
|
||
|
about.</p><p>This part starts with a generalization of the design recipe so that it
|
||
|
works for all forms of <a name="(idx._(gentag._494))"></a>structural data definitions. Next, it introduces
|
||
|
the concept of <a name="(idx._(gentag._495))"></a>iterative refinement from <a href="part_two.html#%28part._ch~3aproj-lists%29" data-pltdoc="x">Projects: Lists</a> on a
|
||
|
rigorous basis because complex data definitions are not developed in one
|
||
|
fell swoop but in several stages. Indeed, the use of iterative refinement
|
||
|
is one of the reasons why all programmers are little scientists and why
|
||
|
our discipline uses the word “science” in its American name. Two last
|
||
|
chapters illustrate these ideas: one explains how to design an interpreter
|
||
|
for BSL and another is about processing XML, a data exchange language
|
||
|
for the web. The last chapter expands the design recipe one more time,
|
||
|
reworking it for functions that process two complex arguments at the same
|
||
|
time.</p><h3>19<tt> </tt><a name="(part._ch~3apoetry-sexp)"></a>The Poetry of S-expressions</h3><p>Programming resembles poetry. Like poets, programmers practice their skill
|
||
|
on seemingly pointless ideas. They revise and edit all the time, as the
|
||
|
preceding chapter explains. This chapter introduces increasingly complex
|
||
|
forms of data—<wbr></wbr>seemingly without a real-world purpose. Even when we
|
||
|
provide a motivational background, the chosen kinds of data are pure to an
|
||
|
extreme, and it is unlikely that you will ever encounter them again.</p><p>Nevertheless, this chapter shows the full power of the design recipe and
|
||
|
introduces you to the kinds of data that real-world programs cope with.
|
||
|
To connect this material with what you will encounter in your life as a
|
||
|
programmer, we label each section with appropriate names: trees, forests,
|
||
|
XML. The last one is a bit misleading because it is really about
|
||
|
S-expressions; the connection between S-expressions and XML is clarified
|
||
|
in <a href="part_four.html#%28part._ch~3amoney-sexp%29" data-pltdoc="x">Project: The Commerce of XML</a>, which, in contrast to this chapter, comes much
|
||
|
closer to real-world uses of complex forms of data.</p><h4>19.1<tt> </tt><a name="(part._sec~3abtrees)"></a>Trees</h4><p>All of us have a family tree. One way to draw a family tree is to add an
|
||
|
element every time a child is born and to connect the elements of the
|
||
|
father and mother. For those people whose parents are unknown, there is no
|
||
|
connection to draw. The result is an <span style="font-style: italic">ancestor family tree</span>
|
||
|
because, given any person, the tree points to all of the person’s known
|
||
|
ancestors.</p><blockquote class="Figure"><blockquote class="Centerfigure"><blockquote class="FigureInside"><blockquote class="SCentered"><p><img style="vertical-align: -0.0px; margin: -3px -3px -3px -3px;" src="pict_140.png" alt="image" width="283.2" height="170.78"/></p></blockquote></blockquote></blockquote><p class="Centertext"><span class="Legend"><span class="FigureTarget"><a name="(counter._(figure._fig~3afamily-tree))" x-target-lift="Figure"></a>Figure 111: </span>A family tree</span></p></blockquote><p><a href="part_four.html#%28counter._%28figure._fig~3afamily-tree%29%29" data-pltdoc="x">Figure <span class="FigureRef">111</span></a> displays a three-tier family tree. Gustav is
|
||
|
the child of Eva and Fred, while Eva is the child of Carl and Bettina. In
|
||
|
addition to people’s names and family relationships, the tree also records
|
||
|
years of birth and eye colors. Based on this sketch, you can easily imagine
|
||
|
a family tree reaching back many generations and one that records other
|
||
|
kinds of information.</p><p><div class="SIntrapara">Once a family tree is large, it makes sense to represent it as data and to
|
||
|
design programs that process this kind of data. Given that a point in a
|
||
|
family tree combines five pieces of information—<wbr></wbr>the father, the mother,
|
||
|
the name, the birth date, and the eye color—<wbr></wbr>we should define a structure type:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define-struct%29%29" class="RktStxLink" data-pltdoc="x">define-struct</a></span><span class="hspace"> </span><span class="RktSym">child</span><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym">father</span><span class="hspace"> </span><span class="RktSym">mother</span><span class="hspace"> </span><span class="RktSym">name</span><span class="hspace"> </span><span class="RktSym">date</span><span class="hspace"> </span><span class="RktSym">eyes</span><span class="RktPn">]</span><span class="RktPn">)</span></p></blockquote></div><div class="SIntrapara">The structure type definition calls a data definition:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">A </span><a name="(tech._child)"></a><span style="font-style: italic">Child</span><span class="RktCmt"> is a structure: </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">make-child</span><span class="stt"> </span><a href="part_four.html#%28tech._child%29" class="techoutside" data-pltdoc="x"><span class="techinside">Child</span></a><span class="stt"> </span><a href="part_four.html#%28tech._child%29" class="techoutside" data-pltdoc="x"><span class="techinside">Child</span></a><span class="stt"> </span><a href="part_one.html#%28tech._string%29" class="techoutside" data-pltdoc="x"><span class="techinside">String</span></a><span class="stt"> </span><a href="part_two.html#%28tech._n%29" class="techoutside" data-pltdoc="x"><span class="techinside">N</span></a><span class="stt"> </span><a href="part_one.html#%28tech._string%29" class="techoutside" data-pltdoc="x"><span class="techinside">String</span></a><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">While this data definition looks straightforward, it is also useless. It
|
||
|
refers to itself, but, because it doesn’t have any clauses, there is no way
|
||
|
to create a proper instance <a href="part_four.html#%28tech._child%29" class="techoutside" data-pltdoc="x"><span class="techinside">Child</span></a>. Roughly, we would have to write
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktPn">(</span><span class="RktSym">make-child</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">make-child</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">make-child</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="RktPn">)</span></p></blockquote></div><div class="SIntrapara">without end. To avoid such pointless data definitions, we demand that a
|
||
|
self-referential data definition have several clauses and that at
|
||
|
least one of them does not refer back to the data definition.</div></p><p><div class="SIntrapara">Let’s postpone the data definition for a moment, and experiment instead.
|
||
|
Suppose we are about to add a child to an existing family tree and that we
|
||
|
already have representations for the parents. In that case, we can simply
|
||
|
construct a new <span class="RktSym">child</span> structure. For example, to represent Adam in a
|
||
|
program that already represents Carl and Bettina, it suffices to add the
|
||
|
following <span class="RktSym">child</span> structure:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">Adam</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">make-child</span><span class="hspace"> </span><span class="RktSym">Carl</span><span class="hspace"> </span><span class="RktSym">Bettina</span><span class="hspace"> </span><span class="RktVal">"Adam"</span><span class="hspace"> </span><span class="RktVal">1950</span><span class="hspace"> </span><span class="RktVal">"hazel"</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">assuming <span class="RktSym">Carl</span> and <span class="RktSym">Bettina</span> stand for representations of
|
||
|
Adam’s parents.</div></p><p><div class="SIntrapara">Then again, a person’s parents may be unknown, like Bettina’s in the family
|
||
|
tree of <a href="part_four.html#%28counter._%28figure._fig~3afamily-tree%29%29" data-pltdoc="x">figure <span class="FigureRef">111</span></a>. Yet, even then, we must fill the
|
||
|
corresponding parent field(s) in the <span class="RktSym">child</span> representation.
|
||
|
Whatever data we choose, it must signal an absence of information. On
|
||
|
the one hand, we could use <span class="RktVal">#false</span>, <span class="RktVal">"none"</span>, or <span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span>
|
||
|
from the pool of existing values. On the other hand, we should really say
|
||
|
that the information is missing from a family tree. We can achieve this
|
||
|
objective best with the introduction of a structure type with an
|
||
|
appropriate name:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define-struct%29%29" class="RktStxLink" data-pltdoc="x">define-struct</a></span><span class="hspace"> </span><span class="RktSym">no-parent</span><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">]</span><span class="RktPn">)</span></p></blockquote></div><div class="SIntrapara">Now, to construct a <span class="RktSym">child</span> structure for Bettina, we say
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym">make-child</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">make-no-parent</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">make-no-parent</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">"Bettina"</span><span class="hspace"> </span><span class="RktVal">1926</span><span class="hspace"> </span><span class="RktVal">"green"</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">Of course, if only one piece of information is missing, we fill just that
|
||
|
field with this special value.</div></p><p><div class="SIntrapara">Our experimentation suggests two insights. First, we are <span style="font-weight: bold">not</span> looking for a data
|
||
|
definition that describes how to generate instances of <span class="RktSym">child</span>
|
||
|
structures but for a data definition that describes how to represent family
|
||
|
trees. Second, the data definition consists of two clauses, one for the variant
|
||
|
describing unknown family trees and another one for known family trees:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define-struct%29%29" class="RktStxLink" data-pltdoc="x">define-struct</a></span><span class="hspace"> </span><span class="RktSym">no-parent</span><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">]</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define-struct%29%29" class="RktStxLink" data-pltdoc="x">define-struct</a></span><span class="hspace"> </span><span class="RktSym">child</span><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym">father</span><span class="hspace"> </span><span class="RktSym">mother</span><span class="hspace"> </span><span class="RktSym">name</span><span class="hspace"> </span><span class="RktSym">date</span><span class="hspace"> </span><span class="RktSym">eyes</span><span class="RktPn">]</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">An </span><a name="(tech._ft)"></a><span style="font-style: italic">FT</span><span class="RktCmt"> (short for </span><span style="font-style: italic">family tree</span><span class="RktCmt">) is one of: </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">–</span><span class="RktCmt"> </span><span class="RktPn">(</span><span class="RktSym">make-no-parent</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">–</span><span class="RktCmt"> </span><span class="RktPn">(</span><span class="RktSym">make-child</span><span class="stt"> </span><a href="part_four.html#%28tech._ft%29" class="techoutside" data-pltdoc="x"><span class="techinside">FT</span></a><span class="stt"> </span><a href="part_four.html#%28tech._ft%29" class="techoutside" data-pltdoc="x"><span class="techinside">FT</span></a><span class="stt"> </span><a href="part_one.html#%28tech._string%29" class="techoutside" data-pltdoc="x"><span class="techinside">String</span></a><span class="stt"> </span><a href="part_two.html#%28tech._n%29" class="techoutside" data-pltdoc="x"><span class="techinside">N</span></a><span class="stt"> </span><a href="part_one.html#%28tech._string%29" class="techoutside" data-pltdoc="x"><span class="techinside">String</span></a><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">Since the “no parent” tree is going to show up a lot in our programs, we
|
||
|
define <span class="RktSym">NP</span> as a short-hand and revise the data definition a bit:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">NP</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">make-no-parent</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">An </span><span style="font-style: italic">FT</span><span class="RktCmt"> is one of: </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">–</span><span class="RktCmt"> </span><span class="RktSym">NP</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">–</span><span class="RktCmt"> </span><span class="RktPn">(</span><span class="RktSym">make-child</span><span class="stt"> </span><a href="part_four.html#%28tech._ft%29" class="techoutside" data-pltdoc="x"><span class="techinside">FT</span></a><span class="stt"> </span><a href="part_four.html#%28tech._ft%29" class="techoutside" data-pltdoc="x"><span class="techinside">FT</span></a><span class="stt"> </span><a href="part_one.html#%28tech._string%29" class="techoutside" data-pltdoc="x"><span class="techinside">String</span></a><span class="stt"> </span><a href="part_two.html#%28tech._n%29" class="techoutside" data-pltdoc="x"><span class="techinside">N</span></a><span class="stt"> </span><a href="part_one.html#%28tech._string%29" class="techoutside" data-pltdoc="x"><span class="techinside">String</span></a><span class="RktPn">)</span></td></tr></table></blockquote></div></p><p><div class="SIntrapara">Following the design recipe from <a href="part_two.html#%28part._ch~3adesign-lists%29" data-pltdoc="x">Designing with Self-Referential Data Definitions</a>, we use the data
|
||
|
definition to create examples of family trees. Specifically, we translate the
|
||
|
family tree in <a href="part_four.html#%28counter._%28figure._fig~3afamily-tree%29%29" data-pltdoc="x">figure <span class="FigureRef">111</span></a> into our data representation. The
|
||
|
information for Carl is easy to translate into data:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktPn">(</span><span class="RktSym">make-child</span><span class="hspace"> </span><span class="RktSym">NP</span><span class="hspace"> </span><span class="RktSym">NP</span><span class="hspace"> </span><span class="RktVal">"Carl"</span><span class="hspace"> </span><span class="RktVal">1926</span><span class="hspace"> </span><span class="RktVal">"green"</span><span class="RktPn">)</span></p></blockquote></div><div class="SIntrapara">Bettina and Fred are represented with similar instances of <span class="RktSym">child</span>. The
|
||
|
case for Adam calls for nested children, one for Carl and one for Bettina:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym">make-child</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">make-child</span><span class="hspace"> </span><span class="RktSym">NP</span><span class="hspace"> </span><span class="RktSym">NP</span><span class="hspace"> </span><span class="RktVal">"Carl"</span><span class="hspace"> </span><span class="RktVal">1926</span><span class="hspace"> </span><span class="RktVal">"green"</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">make-child</span><span class="hspace"> </span><span class="RktSym">NP</span><span class="hspace"> </span><span class="RktSym">NP</span><span class="hspace"> </span><span class="RktVal">"Bettina"</span><span class="hspace"> </span><span class="RktVal">1926</span><span class="hspace"> </span><span class="RktVal">"green"</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">"Adam"</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">1950</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">"hazel"</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">Since the records for Carl and Bettina are also needed to construct the records
|
||
|
for Dave and Eva, it is better to introduce definitions that name specific
|
||
|
instances of <span class="RktSym">child</span> and to use the variable names elsewhere.
|
||
|
<a href="part_four.html#%28counter._%28figure._fig~3afamily.S%29%29" data-pltdoc="x">Figure <span class="FigureRef">112</span></a> illustrates this approach for the complete
|
||
|
data representation of the family tree from <a href="part_four.html#%28counter._%28figure._fig~3afamily-tree%29%29" data-pltdoc="x">figure <span class="FigureRef">111</span></a>. Take
|
||
|
a close look; the tree serves as our running example for the following design
|
||
|
exercise.</div></p><blockquote class="Figure"><blockquote class="Centerfigure"><blockquote class="FigureInside"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">Oldest Generation:</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">Carl</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">make-child</span><span class="hspace"> </span><span class="RktSym">NP</span><span class="hspace"> </span><span class="RktSym">NP</span><span class="hspace"> </span><span class="RktVal">"Carl"</span><span class="hspace"> </span><span class="RktVal">1926</span><span class="hspace"> </span><span class="RktVal">"green"</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">Bettina</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">make-child</span><span class="hspace"> </span><span class="RktSym">NP</span><span class="hspace"> </span><span class="RktSym">NP</span><span class="hspace"> </span><span class="RktVal">"Bettina"</span><span class="hspace"> </span><span class="RktVal">1926</span><span class="hspace"> </span><span class="RktVal">"green"</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">Middle Generation:</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">Adam</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">make-child</span><span class="hspace"> </span><span class="RktSym">Carl</span><span class="hspace"> </span><span class="RktSym">Bettina</span><span class="hspace"> </span><span class="RktVal">"Adam"</span><span class="hspace"> </span><span class="RktVal">1950</span><span class="hspace"> </span><span class="RktVal">"hazel"</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">Dave</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">make-child</span><span class="hspace"> </span><span class="RktSym">Carl</span><span class="hspace"> </span><span class="RktSym">Bettina</span><span class="hspace"> </span><span class="RktVal">"Dave"</span><span class="hspace"> </span><span class="RktVal">1955</span><span class="hspace"> </span><span class="RktVal">"black"</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">Eva</span><span clas
|
||
|
the generic organization of such a function. That is, let’s work through the
|
||
|
design recipe as much as possible without having a concrete task in mind. We
|
||
|
start with the header material, that is, step 2 of the recipe:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_four.html#%28tech._ft%29" class="techoutside" data-pltdoc="x"><span class="techinside">FT</span></a><span class="RktCmt"> -> ???</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span>...</td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">fun-FT</span><span class="hspace"> </span><span class="RktSym">an-ftree</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">Even though we aren’t stating the purpose of the function, we do know
|
||
|
that it consumes a family tree and that this form of data is the main input.
|
||
|
The “???” in the signature says that we don’t know what kind
|
||
|
of data the function produces; the “...” remind us that we don’t know its
|
||
|
purpose.</div></p><p><div class="SIntrapara">The lack of purpose means we cannot make up functional examples. Nevertheless,
|
||
|
we can exploit the organization of the data definition for <span class="RktSym">FT</span> to design
|
||
|
a template. Since it consists of two clauses, the template must consist of a
|
||
|
<span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span> expression with two clauses:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">fun-FT</span><span class="hspace"> </span><span class="RktSym">an-ftree</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym">no-parent?</span><span class="hspace"> </span><span class="RktSym">an-ftree</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._else%29%29" class="RktStxLink" data-pltdoc="x">else</a></span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="RktPn">]</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div></p><p><div class="SIntrapara">In case the argument to <span class="RktSym">fun-FT</span> satisfies <span class="RktSym">no-parent?</span>,
|
||
|
the structure contains no additional data, so the first clause is
|
||
|
complete. For the second clause, the input contains five pieces of
|
||
|
data, which we indicate with five selectors in the template:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_four.html#%28tech._ft%29" class="techoutside" data-pltdoc="x"><span class="techinside">FT</span></a><span class="RktCmt"> -> ???</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">fun-FT</span><span class="hspace"> </span><span class="RktSym">an-ftree</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym">no-parent?</span><span class="hspace"> </span><span class="RktSym">an-ftree</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._else%29%29" class="RktStxLink" data-pltdoc="x">else</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">child-father</span><span class="hspace"> </span><span class="RktSym">an-ftree</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">child-mother</span><span class="hspace"> </span><span class="RktSym">an-ftree</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">child-name</span><span class="hspace"> </span><span class="RktSym">an-ftree</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermedi
|
||
|
data definition refers to itself, the function is likely to recur and
|
||
|
templates indicate so with suggestive natural recursions. The definition
|
||
|
for <a href="part_four.html#%28tech._ft%29" class="techoutside" data-pltdoc="x"><span class="techinside">FT</span></a> has two self-references, and the template therefore
|
||
|
needs two such recursions:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_four.html#%28tech._ft%29" class="techoutside" data-pltdoc="x"><span class="techinside">FT</span></a><span class="RktCmt"> -> ???</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">fun-FT</span><span class="hspace"> </span><span class="RktSym">an-ftree</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym">no-parent?</span><span class="hspace"> </span><span class="RktSym">an-ftree</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._else%29%29" class="RktStxLink" data-pltdoc="x">else</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">fun-FT</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">child-father</span><span class="hspace"> </span><span class="RktSym">an-ftree</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">fun-FT</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">child-mother</span><span class="hspace"> </span><span class="RktSym">an-ftree</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="hspace"> </span><span class="RktPn">(</span><
|
||
|
for fathers and mothers in the second <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span> clause because the
|
||
|
second clause of the data definition contains corresponding self-references.</div></p><p><div class="SIntrapara">Let’s now turn to a concrete example, the <span class="RktSym">blue-eyed-child?</span> function. Its
|
||
|
purpose is to determine whether any <span class="RktSym">child</span> structure in a given
|
||
|
family tree has blue eyes. You may copy, paste, and rename
|
||
|
<span class="RktSym">fun-FT</span> to get its template; we replace “???” with
|
||
|
<a href="part_one.html#%28tech._boolean%29" class="techoutside" data-pltdoc="x"><span class="techinside">Boolean</span></a> and add a purpose statement: <a name="(idx._(gentag._496))"></a>
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_four.html#%28tech._ft%29" class="techoutside" data-pltdoc="x"><span class="techinside">FT</span></a><span class="RktCmt"> -> </span><a href="part_one.html#%28tech._boolean%29" class="techoutside" data-pltdoc="x"><span class="techinside">Boolean</span></a></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">does </span><span class="RktSym">an-ftree</span><span class="RktCmt"> contain a </span><span class="RktSym">child</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">structure with </span><span class="RktVal">"blue"</span><span class="RktCmt"> in the </span><span class="RktSym">eyes</span><span class="RktCmt"> field</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">blue-eyed-child?</span><span class="hspace"> </span><span class="RktSym">an-ftree</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym">no-parent?</span><span class="hspace"> </span><span class="RktSym">an-ftree</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._else%29%29" class="RktStxLink" data-pltdoc="x">else</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">blue-eyed-child?</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">child-father</span><span class="hspace"> </span><span class="RktSym">an-ftree</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">blue-eyed-child?</span></td></tr><tr><td><span class="hspace">
|
||
|
name with a specific one.</div></p><p><div class="SIntrapara">Checking with our recipe, we realize that we need to backtrack and develop
|
||
|
some examples before we move on to the definition step. If we start with Carl,
|
||
|
the first person in the family tree, we see that Carl’s family tree does
|
||
|
not contain a <span class="RktSym">child</span> with a <span class="RktVal">"blue"</span> eye color. Specifically, the
|
||
|
<span class="RktSym">child</span> representing Carl says the eye color is <span class="RktVal">"green"</span>; given
|
||
|
that Carl’s ancestor trees are empty, they cannot possibly contain a <span class="RktSym">child</span>
|
||
|
with <span class="RktVal">"blue"</span> eye color:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._check-expect%29%29" class="RktStxLink" data-pltdoc="x">check-expect</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">blue-eyed-child?</span><span class="hspace"> </span><span class="RktSym">Carl</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">#false</span><span class="RktPn">)</span></p></blockquote></div><div class="SIntrapara">In contrast, <span class="RktSym">Gustav</span> contains a <span class="RktSym">child</span> for <span class="RktSym">Eva</span> who does have blue eyes:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._check-expect%29%29" class="RktStxLink" data-pltdoc="x">check-expect</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">blue-eyed-child?</span><span class="hspace"> </span><span class="RktSym">Gustav</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">#true</span><span class="RktPn">)</span></p></blockquote></div></p><p>Now we are ready to define the actual function. The function distinguishes
|
||
|
between two cases: a <span class="RktSym">no-parent</span> and a <span class="RktSym">child</span>. For the
|
||
|
first case, the answer should be obvious even though we haven’t made up
|
||
|
any examples. Since the given family tree does not contain any
|
||
|
<span class="RktSym">child</span> whatsoever, it cannot contain one with <span class="RktVal">"blue"</span> as the
|
||
|
eye color. Hence the result in the first <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span> clause is
|
||
|
<span class="RktVal">#false</span>.</p><p><div class="SIntrapara">For the second <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span> clause, the design requires a lot more work.
|
||
|
Again following the design recipe, we first remind ourselves what the
|
||
|
expressions in the template accomplish:
|
||
|
</div><div class="SIntrapara"><ol><li><p><div class="SIntrapara">according to the purpose statement for the function,
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktPn">(</span><span class="RktSym">blue-eyed-child?</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">child-father</span><span class="hspace"> </span><span class="RktSym">an-ftree</span><span class="RktPn">)</span><span class="RktPn">)</span></p></blockquote></div><div class="SIntrapara">determines whether some <span class="RktSym">child</span> in the father’s <a href="part_four.html#%28tech._ft%29" class="techoutside" data-pltdoc="x"><span class="techinside">FT</span></a> has
|
||
|
<span class="RktVal">"blue"</span> eyes;</div></p></li><li><p>likewise, <span class="RktPn">(</span><span class="RktSym">blue-eyed-child?</span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym">child-mother</span><span class="stt"> </span><span class="RktSym">an-ftree</span><span class="RktPn">)</span><span class="RktPn">)</span>
|
||
|
determines whether someone in the mother’s <a href="part_four.html#%28tech._ft%29" class="techoutside" data-pltdoc="x"><span class="techinside">FT</span></a> has blue eyes; and</p></li><li><p>the selector expressions <span class="RktPn">(</span><span class="RktSym">child-name</span><span class="stt"> </span><span class="RktSym">an-ftree</span><span class="RktPn">)</span>,
|
||
|
<span class="RktPn">(</span><span class="RktSym">child-date</span><span class="stt"> </span><span class="RktSym">an-ftree</span><span class="RktPn">)</span>, and <span class="RktPn">(</span><span class="RktSym">child-eyes</span><span class="stt"> </span><span class="RktSym">an-ftree</span><span class="RktPn">)</span> extract
|
||
|
the name, birth date, and eye color from the given <span class="RktSym">child</span>
|
||
|
structure, respectively.</p></li></ol></div><div class="SIntrapara">Now we just need to figure out how to combine these expressions.</div></p><p>Clearly, if the <span class="RktSym">child</span> structure contains <span class="RktVal">"blue"</span> in the
|
||
|
<span class="RktSym">eyes</span> field, the function’s answer is <span class="RktVal">#true</span>. Next, the
|
||
|
expressions concerning names and birth dates are useless, which leaves us
|
||
|
with the recursive calls. As stated, <span class="RktPn">(</span><span class="RktSym">blue-eyed-child?</span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym">child-father</span><span class="stt"> </span><span class="RktSym">an-ftree</span><span class="RktPn">)</span><span class="RktPn">)</span> traverses the tree on the father’s side,
|
||
|
while the mother’s side of the family tree is processed with
|
||
|
<span class="RktPn">(</span><span class="RktSym">blue-eyed-child?</span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym">child-mother</span><span class="stt"> </span><span class="RktSym">an-ftree</span><span class="RktPn">)</span><span class="RktPn">)</span>. If either of these
|
||
|
expressions returns <span class="RktVal">#true</span>, <span class="RktSym">an-ftree</span> contains a
|
||
|
<span class="RktSym">child</span> with <span class="RktVal">"blue"</span> eyes.</p><p><div class="SIntrapara">Our analysis suggests that the result should be <span class="RktVal">#true</span> if one of the
|
||
|
following three expressions is <span class="RktVal">#true</span>:
|
||
|
</div><div class="SIntrapara"><ul><li><p><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._string~3d~3f%29%29" class="RktValLink" data-pltdoc="x">string=?</a></span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym">child-eyes</span><span class="stt"> </span><span class="RktSym">an-ftree</span><span class="RktPn">)</span><span class="stt"> </span><span class="RktVal">"blue"</span><span class="RktPn">)</span></p></li><li><p><span class="RktPn">(</span><span class="RktSym">blue-eyed-child?</span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym">child-father</span><span class="stt"> </span><span class="RktSym">an-ftree</span><span class="RktPn">)</span><span class="RktPn">)</span></p></li><li><p><span class="RktPn">(</span><span class="RktSym">blue-eyed-child?</span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym">child-mother</span><span class="stt"> </span><span class="RktSym">an-ftree</span><span class="RktPn">)</span><span class="RktPn">)</span></p></li></ul></div><div class="SIntrapara">which, in turn, means we need to combine these expressions with <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._or%29%29" class="RktStxLink" data-pltdoc="x">or</a></span>:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._or%29%29" class="RktStxLink" data-pltdoc="x">or</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._string~3d~3f%29%29" class="RktValLink" data-pltdoc="x">string=?</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">child-eyes</span><span class="hspace"> </span><span class="RktSym">an-ftree</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">"blue"</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">blue-eyed-child?</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">child-father</span><span class="hspace"> </span><span class="RktSym">an-ftree</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">blue-eyed-child?</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">child-mother</span><span class="hspace"> </span><span class="RktSym">an-ftree</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara"><a href="part_four.html#%28counter._%28figure._fig~3ablue-eyes%29%29" data-pltdoc="x">Figure <span class="FigureRef">113</span></a> pulls everything together in a single
|
||
|
definition.</div></p><p><div class="SIntrapara"><a name="(idx._(gentag._497))"></a>
|
||
|
</div><div class="SIntrapara"><blockquote class="Figure"><blockquote class="Centerfigure"><blockquote class="FigureInside"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_four.html#%28tech._ft%29" class="techoutside" data-pltdoc="x"><span class="techinside">FT</span></a><span class="RktCmt"> -> </span><a href="part_one.html#%28tech._boolean%29" class="techoutside" data-pltdoc="x"><span class="techinside">Boolean</span></a></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">does </span><span class="RktSym">an-ftree</span><span class="RktCmt"> contain a </span><span class="RktSym">child</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">structure with </span><span class="RktVal">"blue"</span><span class="RktCmt"> in the </span><span class="RktSym">eyes</span><span class="RktCmt"> field</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._check-expect%29%29" class="RktStxLink" data-pltdoc="x">check-expect</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">blue-eyed-child?</span><span class="hspace"> </span><span class="RktSym">Carl</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">#false</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._check-expect%29%29" class="RktStxLink" data-pltdoc="x">check-expect</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">blue-eyed-child?</span><span class="hspace"> </span><span class="RktSym">Gustav</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">#true</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">blue-eyed-child?</span><span class="hspace"> </span><span class="RktSym">an-ftree</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym">no-parent?</span><span class="hspace"> </span><span class="RktSym">an-ftree</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">#false</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._else%29%29" class="RktStxLink" data-pltdoc="x">else</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._or%29%29" class="RktStxLink" data-pltdoc="x">or</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-la
|
||
|
simulate the stepper’s action for <span class="RktPn">(</span><span class="RktSym">blue-eyed-child?</span><span class="stt"> </span><span class="RktSym">Carl</span><span class="RktPn">)</span> to give
|
||
|
you an impression of how it all works:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym">blue-eyed-child?</span><span class="hspace"> </span><span class="RktSym">Carl</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktSym">==</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym">blue-eyed-child?</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">make-child</span><span class="hspace"> </span><span class="RktSym">NP</span><span class="hspace"> </span><span class="RktSym">NP</span><span class="hspace"> </span><span class="RktVal">"Carl"</span><span class="hspace"> </span><span class="RktVal">1926</span><span class="hspace"> </span><span class="RktVal">"green"</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">Let’s act as if <span class="RktSym">NP</span> were a value and let’s use <span class="RktSym">carl</span> as an
|
||
|
abbreviation for the instance of <span class="RktSym">child</span>:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktSym">==</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym">no-parent?</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">make-child</span><span class="hspace"> </span><span class="RktSym">NP</span><span class="hspace"> </span><span class="RktSym">NP</span><span class="hspace"> </span><span class="RktVal">"Carl"</span><span class="hspace"> </span><span class="RktVal">1926</span><span class="hspace"> </span><span class="RktVal">"green"</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">#false</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._else%29%29" class="RktStxLink" data-pltdoc="x">else</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._or%29%29" class="RktStxLink" data-pltdoc="x">or</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._string~3d~3f%29%29" class="RktValLink" data-pltdoc="x">string=?</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">child-eyes</span><span class="hspace"> </span><span class="RktSym">carl</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">"blue"</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">blue-eyed-child?</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">child-father</span><span class="hspace"> </span><span class="RktSym">carl</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">blue-eyed-child?</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">child-mother</span><span class="hspace"> </span><span class="RktSym">carl</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">]</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">After dropping the first <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span> line, it’s time to replace
|
||
|
<span class="RktSym">carl</span> with its value and to perform the three auxiliary
|
||
|
calculations in <a href="part_four.html#%28counter._%28figure._fig~3acalc-trees%29%29" data-pltdoc="x">figure <span class="FigureRef">114</span></a>. Using these to replace equals
|
||
|
with equals, the rest of the computation is explained easily:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktSym">==</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._or%29%29" class="RktStxLink" data-pltdoc="x">or</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._string~3d~3f%29%29" class="RktValLink" data-pltdoc="x">string=?</a></span><span class="hspace"> </span><span class="RktVal">"green"</span><span class="hspace"> </span><span class="RktVal">"blue"</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">blue-eyed-child?</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">child-father</span><span class="hspace"> </span><span class="RktSym">carl</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">blue-eyed-child?</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">child-mother</span><span class="hspace"> </span><span class="RktSym">carl</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktSym">==</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._or%29%29" class="RktStxLink" data-pltdoc="x">or</a></span><span class="hspace"> </span><span class="RktVal">#false</span><span class="hspace"> </span><span class="RktVal">#false</span><span class="hspace"> </span><span class="RktVal">#false</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktSym">==</span><span class="hspace"> </span><span class="RktVal">#false</span></td></tr></table></blockquote></div><div class="SIntrapara">While we trust that you have seen such auxiliary calculations in your
|
||
|
mathematics courses, you also need to understand that the stepper would
|
||
|
<span style="font-weight: bold">not</span> perform such calculations; instead it works out only those
|
||
|
calculations that are absolutely needed.</div></p><blockquote class="Herefigure"><blockquote class="Centerfigure"><blockquote class="FigureInside"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">(1)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym">child-eyes</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">make-child</span><span class="hspace"> </span><span class="RktSym">NP</span><span class="hspace"> </span><span class="RktSym">NP</span><span class="hspace"> </span><span class="RktVal">"Carl"</span><span class="hspace"> </span><span class="RktVal">1926</span><span class="hspace"> </span><span class="RktVal">"green"</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktSym">==</span></td></tr><tr><td><span class="RktVal">"green"</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">(2)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym">blue-eyed-child?</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">child-father</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">make-child</span><span class="hspace"> </span><span class="RktSym">NP</span><span class="hspace"> </span><span class="RktSym">NP</span><span class="hspace"> </span><span class="RktVal">"Carl"</span><span class="hspace"> </span><span class="RktVal">1926</span><span class="hspace"> </span><span class="RktVal">"green"</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktSym">==</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym">blue-eyed-child?</span><span class="hspace"> </span><span class="RktSym">NP</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktSym">==</span></td></tr><tr><td><span class="RktVal">#false</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">(3)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym">blue-eyed-child?</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">child-mother</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">make-child</span><span class="hspace"> </span><span class="RktSym">NP</span><span class="hspace"> </span><span class="RktSym">NP</span><span class="hspace"> </span><span class="RktVal">"Carl"</span><span class="hspace"> </span><span class="RktVal">1926</span><span class="hspace"> </span><span class="RktVal">"green"</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktSym">==</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym">blue-eyed-child?</span><span class="hspace"> </span><span class="RktSym">NP</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktSym">==</span></td></tr><tr><td><span class="RktVal">#false</span></td></tr></table></blockquote></blockquote></blockquote><p class="Centertext"><span class="Legend"><span class="FigureTarget"><a name="(counter._(figure._fig~3acalc-trees))" x-target-lift="Figure"></a>Figure 114: </span>Calculating with trees</span></p></blockquote><p><a name="(counter._(exercise._ex~3acount-ft))"></a><span style="font-weight: bold">Exercise</span> 310. Develop <span class="RktSym">count-persons</span>. The function
|
||
|
consumes a family tree and counts the <span class="RktSym">child</span> structures in the
|
||
|
tree. <a href="part_four.html#%28counter._%28exercise._ex~3acount-ft%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._(exercise._ex~3aage-ft))"></a><span style="font-weight: bold">Exercise</span> 311. Develop the function <span class="RktSym">average-age</span>. It
|
||
|
consumes a family tree and the current year. It produces the average
|
||
|
age of all <span class="RktSym">child</span> structures in the family tree. <a href="part_four.html#%28counter._%28exercise._ex~3aage-ft%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._(exercise._ex~3aec-ft))"></a><span style="font-weight: bold">Exercise</span> 312. Develop the function <span class="RktSym">eye-colors</span>, which
|
||
|
consumes a family tree and produces a list of all eye colors in the
|
||
|
tree. An eye color may occur more than once in the resulting list.
|
||
|
<span style="font-weight: bold">Hint</span> Use <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._append%29%29" class="RktValLink" data-pltdoc="x">append</a></span> to concatenate the lists resulting from the
|
||
|
recursive calls. <a href="part_four.html#%28counter._%28exercise._ex~3aec-ft%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._(exercise._ex~3aproper-bea))"></a><span style="font-weight: bold">Exercise</span> 313. Suppose we need the function
|
||
|
<span class="RktSym">blue-eyed-ancestor?</span>, which is like <span class="RktSym">blue-eyed-child?</span> but
|
||
|
responds with <span class="RktVal">#true</span> only when a proper ancestor, not the given
|
||
|
<span class="RktSym">child</span> itself, has blue eyes.</p><p><div class="SIntrapara">Although the goals clearly differ, the signatures are the same:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_four.html#%28tech._ft%29" class="techoutside" data-pltdoc="x"><span class="techinside">FT</span></a><span class="RktCmt"> -> </span><a href="part_one.html#%28tech._boolean%29" class="techoutside" data-pltdoc="x"><span class="techinside">Boolean</span></a></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">blue-eyed-ancestor?</span><span class="hspace"> </span><span class="RktSym">an-ftree</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">Stop! Formulate a purpose statement for the function.</div></p><p><div class="SIntrapara">To appreciate the difference, we take a look at Eva:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._check-expect%29%29" class="RktStxLink" data-pltdoc="x">check-expect</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">blue-eyed-child?</span><span class="hspace"> </span><span class="RktSym">Eva</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">#true</span><span class="RktPn">)</span></p></blockquote></div><div class="SIntrapara">Eva is blue-eyed, but has no blue-eyed ancestor. Hence,
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._check-expect%29%29" class="RktStxLink" data-pltdoc="x">check-expect</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">blue-eyed-ancestor?</span><span class="hspace"> </span><span class="RktSym">Eva</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">#false</span><span class="RktPn">)</span></p></blockquote></div><div class="SIntrapara">In contrast, Gustav is Eva’s son and does have a blue-eyed ancestor:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._check-expect%29%29" class="RktStxLink" data-pltdoc="x">check-expect</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">blue-eyed-ancestor?</span><span class="hspace"> </span><span class="RktSym">Gustav</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">#true</span><span class="RktPn">)</span></p></blockquote></div></p><p><div class="SIntrapara">Now suppose a friend comes up with this solution:<a name="(idx._(gentag._498))"></a>
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">blue-eyed-ancestor?</span><span class="hspace"> </span><span class="RktSym">an-ftree</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym">no-parent?</span><span class="hspace"> </span><span class="RktSym">an-ftree</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">#false</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._else%29%29" class="RktStxLink" data-pltdoc="x">else</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._or%29%29" class="RktStxLink" data-pltdoc="x">or</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">blue-eyed-ancestor?</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">child-father</span><span class="hspace"> </span><span class="RktSym">an-ftree</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">blue-eyed-ancestor?</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">child-mother</span><span class="hspace"> </span><span class="RktSym">an-ftree</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">Explain why this function fails one of its tests. What is the result of
|
||
|
<span class="RktPn">(</span><span class="RktSym">blue-eyed-ancestor?</span><span class="stt"> </span><span class="RktSym">A</span><span class="RktPn">)</span> no matter which <span class="RktSym">A</span> you choose?
|
||
|
Can you fix your friend’s solution? <a href="part_four.html#%28counter._%28exercise._ex~3aproper-bea%29%29" class="ex-end" data-pltdoc="x"></a></div></p><p><span style="font-weight: bold">Note on variable and structure names</span> The initial discussion of family
|
||
|
relationships suggests the name <span class="RktSym">child</span> for the structure type
|
||
|
definition. The five pieces of information represent the child of particular
|
||
|
parents. The rest of the development is about ancestor trees, however. If you
|
||
|
were to skim the chapter just to focus on function definitions, like the one in
|
||
|
<a href="part_four.html#%28counter._%28figure._fig~3ablue-eyes%29%29" data-pltdoc="x">figure <span class="FigureRef">113</span></a>, the names <span class="RktSym">child-father</span>,
|
||
|
<span class="RktSym">child-mother</span>, and <span class="RktSym">child-eyes</span> might mislead you a bit, mostly
|
||
|
because they might seem to conflict with the recursive nature of the function.
|
||
|
An experienced developer would probably use DrRacket’s renaming
|
||
|
functionality<span class="refelem"><span class="refcolumn"><span class="refcontent">Check syntax. Right-click on the name of the
|
||
|
structure. Select rename.</span></span></span> to replace <span class="RktSym">child</span> with <span class="RktSym">person</span>. In
|
||
|
general, variable naming are critical for
|
||
|
helping readers of code to understand the thinking behind it.</p><h4>19.2<tt> </tt><a name="(part._sec~3aforests)"></a>Forests</h4><p><div class="SIntrapara">It is a short step from a family tree to a family forest:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">An </span><a name="(tech._ff)"></a><span style="font-style: italic">FF</span><span class="RktCmt"> (short for </span><span style="font-style: italic">family forest</span><span class="RktCmt">) is one of: </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">–</span><span class="RktCmt"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">–</span><span class="RktCmt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="stt"> </span><a href="part_four.html#%28tech._ft%29" class="techoutside" data-pltdoc="x"><span class="techinside">FT</span></a><span class="stt"> </span><a href="part_four.html#%28tech._ff%29" class="techoutside" data-pltdoc="x"><span class="techinside">FF</span></a><span class="RktPn">)</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span style="font-weight: bold">interpretation</span><span class="RktCmt"> a family forest represents several</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">families (say, a town) and their ancestor trees</span></td></tr></table></blockquote></div><div class="SIntrapara">Here are some tree excerpts from <a href="part_four.html#%28counter._%28figure._fig~3afamily-tree%29%29" data-pltdoc="x">figure <span class="FigureRef">111</span></a> arranged as forests:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">ff1</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktSym">Carl</span><span class="hspace"> </span><span class="RktSym">Bettina</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">ff2</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktSym">Fred</span><span class="hspace"> </span><span class="RktSym">Eva</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">ff3</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktSym">Fred</span><span class="hspace"> </span><span class="RktSym">Eva</span><span class="hspace"> </span><span class="RktSym">Carl</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">The first two forests contain two unrelated families, and the third one
|
||
|
illustrates that unlike in real forests, trees in family forests can
|
||
|
overlap.</div></p><p><div class="SIntrapara">Now consider this representative problem concerning family trees:
|
||
|
</div><div class="SIntrapara"><blockquote><p><span style="font-weight: bold">Sample Problem</span> Design the function <span class="RktSym">blue-eyed-child-in-forest?</span>, which
|
||
|
determines whether a family forest contains a <span class="RktSym">child</span> with
|
||
|
<span class="RktVal">"blue"</span> in the <span class="RktSym">eyes</span> field.</p></blockquote></div></p><p><div class="SIntrapara"><a name="(idx._(gentag._499))"></a>
|
||
|
</div><div class="SIntrapara"><blockquote class="Herefigure"><blockquote class="Centerfigure"><blockquote class="FigureInside"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_four.html#%28tech._ff%29" class="techoutside" data-pltdoc="x"><span class="techinside">FF</span></a><span class="RktCmt"> -> </span><a href="part_one.html#%28tech._boolean%29" class="techoutside" data-pltdoc="x"><span class="techinside">Boolean</span></a></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">does the forest contain any </span><span class="RktSym">child</span><span class="RktCmt"> with </span><span class="RktVal">"blue"</span><span class="RktCmt"> </span><span class="RktSym">eyes</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._check-expect%29%29" class="RktStxLink" data-pltdoc="x">check-expect</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">blue-eyed-child-in-forest?</span><span class="hspace"> </span><span class="RktSym">ff1</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">#false</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._check-expect%29%29" class="RktStxLink" data-pltdoc="x">check-expect</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">blue-eyed-child-in-forest?</span><span class="hspace"> </span><span class="RktSym">ff2</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">#true</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._check-expect%29%29" class="RktStxLink" data-pltdoc="x">check-expect</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">blue-eyed-child-in-forest?</span><span class="hspace"> </span><span class="RktSym">ff3</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">#true</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">blue-eyed-child-in-forest?</span><span class="hspace"> </span><span class="RktSym">a-forest</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._empty~3f%29%29" class="RktValLink" data-pltdoc="x">empty?</a></span><span class="hspace"> </span><span class="RktSym">a-forest</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">#false</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span cl
|
||
|
Study the signature, the purpose statement, and the examples on your own. We
|
||
|
focus on the program organization. Concerning the template, the design may
|
||
|
employ the list template because the function consumes a list. If each item on
|
||
|
the list were a structure with an <span class="RktSym">eyes</span> field and nothing else, the
|
||
|
function would iterate over those structures using the selector function for
|
||
|
the <span class="RktSym">eyes</span> field and a string comparison. In this case, each item is a
|
||
|
family tree, but, luckily, we already know how to process family trees.</p><p>Let’s step back and inspect how we explained
|
||
|
<a href="part_four.html#%28counter._%28figure._fig~3ablue-eyed-child%29%29" data-pltdoc="x">figure <span class="FigureRef">115</span></a>. The starting point is a <span style="font-weight: bold">pair</span> of data
|
||
|
definitions where the second refers to the first and both refer to
|
||
|
themselves. The result is a <span style="font-weight: bold">pair</span> of functions where the second refers
|
||
|
to the first and both refer to themselves. In other words, the function
|
||
|
definitions refer to each other the same way the data definitions refer to
|
||
|
each other. Early chapters gloss over this kind of relationship, but now the
|
||
|
situation is sufficiently complicated and deserves attention.</p><p><a name="(counter._(exercise._ex~3afamily-forest1))"></a><span style="font-weight: bold">Exercise</span> 314. Reformulate the data definition for <a href="part_four.html#%28tech._ff%29" class="techoutside" data-pltdoc="x"><span class="techinside">FF</span></a>
|
||
|
with the <a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a> abstraction. Now do the same for
|
||
|
the <span class="RktSym">blue-eyed-child-in-forest?</span> function. Finally, define
|
||
|
<span class="RktSym">blue-eyed-child-in-forest?</span> using one of the list abstractions from
|
||
|
the preceding chapter. <a href="part_four.html#%28counter._%28exercise._ex~3afamily-forest1%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._(exercise._ex~3afamily-forest2))"></a><span style="font-weight: bold">Exercise</span> 315. Design the function <span class="RktSym">average-age</span>. It
|
||
|
consumes a family forest and a year (<a href="part_two.html#%28tech._n%29" class="techoutside" data-pltdoc="x"><span class="techinside">N</span></a>). From this data, it
|
||
|
produces the average age of all <span class="RktSym">child</span> instances in the
|
||
|
forest. <span style="font-weight: bold">Note</span> If the trees in this forest overlap, the result isn’t
|
||
|
a true average because some people contribute more than others. For this
|
||
|
exercise, act as if the trees don’t overlap. <a href="part_four.html#%28counter._%28exercise._ex~3afamily-forest2%29%29" class="ex-end" data-pltdoc="x"></a></p><h4>19.3<tt> </tt><a name="(part._sec~3asexp)"></a>S-expressions</h4><p><div class="SIntrapara">While <a href="i2-3.html" data-pltdoc="x">Intermezzo 2: Quote, Unquote</a> introduced S-expressions on an informal basis, it is
|
||
|
possible to describe them with a combination of three data
|
||
|
definitions:
|
||
|
</div><div class="SIntrapara"><blockquote><table cellspacing="0" cellpadding="0"><tr><td align="left" valign="top"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">An </span><a name="(tech._s._expr)"></a><span style="font-style: italic">S-expr</span><span class="RktCmt"> is one of: </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">–</span><span class="RktCmt"> </span><a href="part_four.html#%28tech._atom%29" class="techoutside" data-pltdoc="x"><span class="techinside">Atom</span></a></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">–</span><span class="RktCmt"> </span><a href="part_four.html#%28tech._sl%29" class="techoutside" data-pltdoc="x"><span class="techinside">SL</span></a></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">An </span><a name="(tech._sl)"></a><span style="font-style: italic">SL</span><span class="RktCmt"> is one of: </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">–</span><span class="RktCmt"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">–</span><span class="RktCmt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="stt"> </span><a href="part_four.html#%28tech._s._expr%29" class="techoutside" data-pltdoc="x"><span class="techinside">S-expr</span></a><span class="stt"> </span><a href="part_four.html#%28tech._sl%29" class="techoutside" data-pltdoc="x"><span class="techinside">SL</span></a><span class="RktPn">)</span></td></tr></table></td><td align="left" valign="top"><p><span class="hspace"> </span></p></td><td align="left" valign="top"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">An </span><a name="(tech._atom)"></a><span style="font-style: italic">Atom</span><span class="RktCmt"> is one of: </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">–</span><span class="RktCmt"> </span><a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">–</span><span class="RktCmt"> </span><a href="part_one.html#%28tech._string%29" class="techoutside" data-pltdoc="x"><span class="techinside">String</span></a></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">–</span><span class="RktCmt"> </span><a href="i2-3.html#%28tech._symbol%29" class="techoutside" data-pltdoc="x"><span class="techinside">Symbol</span></a><span class="RktCmt"> </span></td></tr></table></td></tr></table></blockquote></div><div class="SIntrapara">Recall that <a href="i2-3.html#%28tech._symbol%29" class="techoutside" data-pltdoc="x"><span class="techinside">Symbol</span></a>s look like strings with a
|
||
|
single quote at the beginning and with no quote at the end.</div></p><p>The idea of S-expressions is due to John McCarthy and his Lispers, who
|
||
|
created S-expressions in 1958 so that they could process Lisp programs with
|
||
|
other Lisp programs. This seemingly circular reasoning may sound esoteric,
|
||
|
but, as mentioned in <a href="i2-3.html" data-pltdoc="x">Intermezzo 2: Quote, Unquote</a>, S-expressions are a versatile form of
|
||
|
data that is often rediscovered, most recently with applications to the
|
||
|
world wide web. Working with S-expressions thus prepares a discussion of
|
||
|
how to design functions for highly intertwined data definitions.</p><p><a name="(counter._(exercise._ex~3aatom))"></a><span style="font-weight: bold">Exercise</span> 316. Define the <span class="RktSym">atom?</span> function. <a href="part_four.html#%28counter._%28exercise._ex~3aatom%29%29" class="ex-end" data-pltdoc="x"></a></p><p><div class="SIntrapara">Up to this point in this book, no data has required a data definition as
|
||
|
complex as the one for S-expressions. And yet, with one extra hint, you
|
||
|
can design functions that process S-expressions if you follow the design
|
||
|
recipe. To demonstrate this point, let’s work through a specific example:
|
||
|
</div><div class="SIntrapara"><blockquote><p><span style="font-weight: bold">Sample Problem</span> Design the function <span class="RktSym">count</span>, which determines
|
||
|
how many times some symbol occurs in some S-expression.</p></blockquote></div><div class="SIntrapara">While the first step calls for data definitions and appears to have been
|
||
|
completed, remember that it also calls for the creation of data examples,
|
||
|
especially when the definition is complex.</div></p><p><div class="SIntrapara">A data definition is supposed to be a prescription of how to create data,
|
||
|
and its “test” is whether it is usable. One point that the data
|
||
|
definition for <a href="part_four.html#%28tech._s._expr%29" class="techoutside" data-pltdoc="x"><span class="techinside">S-expr</span></a> makes is that every <a href="part_four.html#%28tech._atom%29" class="techoutside" data-pltdoc="x"><span class="techinside">Atom</span></a> is an element
|
||
|
of <a href="part_four.html#%28tech._s._expr%29" class="techoutside" data-pltdoc="x"><span class="techinside">S-expr</span></a>, and you know that <a href="part_four.html#%28tech._atom%29" class="techoutside" data-pltdoc="x"><span class="techinside">Atom</span></a>s are easy to fabricate:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktVal">'</span><span class="RktVal">hello</span></td></tr><tr><td><span class="RktVal">20.12</span></td></tr><tr><td><span class="RktVal">"world"</span></td></tr></table></blockquote></div><div class="SIntrapara">In the same vein, every <a href="part_four.html#%28tech._sl%29" class="techoutside" data-pltdoc="x"><span class="techinside">SL</span></a> is a list as well as an <a href="part_four.html#%28tech._s._expr%29" class="techoutside" data-pltdoc="x"><span class="techinside">S-expr</span></a>:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">hello</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="hspace"> </span><span class="RktVal">20.12</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="hspace"> </span><span class="RktVal">"world"</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">hello</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="hspace"> </span><span class="RktVal">20.12</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="hspace"> </span><span class="RktVal">"world"</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">The first two are obvious; the third one deserves a second look. It repeats
|
||
|
the second <a href="part_four.html#%28tech._s._expr%29" class="techoutside" data-pltdoc="x"><span class="techinside">S-expr</span></a> but nested inside <span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="stt"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="stt"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span><span class="RktPn">)</span>. What
|
||
|
this means is that it is a list that contains a single item, namely,
|
||
|
the second example. You can simplify the example with <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span>:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">hello</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="hspace"> </span><span class="RktVal">20.12</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="hspace"> </span><span class="RktVal">"world"</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">or </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">hello</span><span class="hspace"> </span><span class="RktVal">20.12</span><span class="hspace"> </span><span class="RktVal">"world"</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div></p><p><div class="SIntrapara">Indeed, with the quotation mechanism of <a href="i2-3.html" data-pltdoc="x">Intermezzo 2: Quote, Unquote</a> it is even easier to
|
||
|
write down S-expressions. Here are the last three:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span></td></tr><tr><td><p><span class="RktRes">'()</span></p></td></tr><tr><td><span class="stt">> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">hello</span><span class="hspace"> </span><span class="RktVal">20.12</span><span class="hspace"> </span><span class="RktVal">"world"</span><span class="RktVal">)</span></td></tr><tr><td><p><span class="RktRes">(list 'hello #i20.12 "world")</span></p></td></tr><tr><td><span class="stt">> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">(</span><span class="RktVal">hello</span><span class="hspace"> </span><span class="RktVal">20.12</span><span class="hspace"> </span><span class="RktVal">"world"</span><span class="RktVal">)</span><span class="RktVal">)</span></td></tr><tr><td><p><span class="RktRes">(list (list 'hello #i20.12 "world"))</span></p></td></tr></table></blockquote></div><div class="SIntrapara">To help you out, we evaluate these examples in the interactions area of
|
||
|
DrRacket so that you can see the result, which is closer to the above
|
||
|
constructions than the <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._quote%29%29" class="RktStxLink" data-pltdoc="x">quote</a></span> notation.</div></p><p><div class="SIntrapara">With <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._quote%29%29" class="RktStxLink" data-pltdoc="x">quote</a></span>, it is quite easy to make up complex examples:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">define</span><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">f</span><span class="hspace"> </span><span class="RktVal">x</span><span class="RktVal">)</span></td></tr><tr><td><span class="hspace"> </span><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">+</span><span class="hspace"> </span><span class="RktVal">x</span><span class="hspace"> </span><span class="RktVal">55</span><span class="RktVal">)</span><span class="RktVal">)</span></td></tr></table></td></tr><tr><td><p><span class="RktRes">(list 'define (list 'f 'x) (list '+ 'x 55))</span></p></td></tr></table></blockquote></div><div class="SIntrapara">This example may strike you as odd because it looks like a definition in
|
||
|
BSL, but, as the interaction with DrRacket shows, it is just a piece of
|
||
|
data. Here is another one:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">(</span><span class="RktVal">6</span><span class="hspace"> </span><span class="RktVal">f</span><span class="RktVal">)</span></td></tr><tr><td><span class="hspace"> </span><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">5</span><span class="hspace"> </span><span class="RktVal">e</span><span class="RktVal">)</span></td></tr><tr><td><span class="hspace"> </span><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">4</span><span class="hspace"> </span><span class="RktVal">d</span><span class="RktVal">)</span><span class="RktVal">)</span></td></tr></table></td></tr><tr><td><p><span class="RktRes">(list (list 6 'f) (list 5 'e) (list 4 'd))</span></p></td></tr></table></blockquote></div><div class="SIntrapara">This piece of data looks like a table, associating letters with
|
||
|
numbers. The last example is a piece of art:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">wing</span><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">wing</span><span class="hspace"> </span><span class="RktVal">body</span><span class="hspace"> </span><span class="RktVal">wing</span><span class="RktVal">)</span><span class="hspace"> </span><span class="RktVal">wing</span><span class="RktVal">)</span></td></tr><tr><td><p><span class="RktRes">(list 'wing (list 'wing 'body 'wing) 'wing)</span></p></td></tr></table></blockquote></div></p><p><div class="SIntrapara">It is now time to write down the rather obvious header for <span class="RktSym">count</span>:<a name="(idx._(gentag._500))"></a>
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_four.html#%28tech._s._expr%29" class="techoutside" data-pltdoc="x"><span class="techinside">S-expr</span></a><span class="RktCmt"> </span><a href="i2-3.html#%28tech._symbol%29" class="techoutside" data-pltdoc="x"><span class="techinside">Symbol</span></a><span class="RktCmt"> -> </span><a href="part_two.html#%28tech._n%29" class="techoutside" data-pltdoc="x"><span class="techinside">N</span></a><span class="RktCmt"> </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">counts all occurrences of </span><span class="RktSym">sy</span><span class="RktCmt"> in </span><span class="RktSym">sexp</span><span class="RktCmt"> </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">count</span><span class="hspace"> </span><span class="RktSym">sexp</span><span class="hspace"> </span><span class="RktSym">sy</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">0</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">Since the header is obvious, we move on to functional examples.
|
||
|
If the given <a href="part_four.html#%28tech._s._expr%29" class="techoutside" data-pltdoc="x"><span class="techinside">S-expr</span></a> is <span class="RktVal">'</span><span class="RktVal">world</span> and the to-be-counted symbol
|
||
|
is <span class="RktVal">'</span><span class="RktVal">world</span>, the answer is obviously <span class="RktVal">1</span>. Here are some more
|
||
|
examples, immediately formulated as tests:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._check-expect%29%29" class="RktStxLink" data-pltdoc="x">check-expect</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">count</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">world</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">hello</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">0</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._check-expect%29%29" class="RktStxLink" data-pltdoc="x">check-expect</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">count</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">world</span><span class="hspace"> </span><span class="RktVal">hello</span><span class="RktVal">)</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">hello</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">1</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._check-expect%29%29" class="RktStxLink" data-pltdoc="x">check-expect</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">count</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">(</span><span class="RktVal">(</span><span class="RktVal">world</span><span class="RktVal">)</span><span class="hspace"> </span><span class="RktVal">hello</span><span class="RktVal">)</span><span class="hspace"> </span><span class="RktVal">hello</span><span class="RktVal">)</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">hello</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">2</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">You can see how convenient quotation notation is for test cases. When it
|
||
|
comes to templates, however, thinking in terms of <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._quote%29%29" class="RktStxLink" data-pltdoc="x">quote</a></span> is disastrous.</div></p><p><div class="SIntrapara">Before we move on to the template step, we need to prepare you for the next
|
||
|
generalization of the design recipe:
|
||
|
</div><div class="SIntrapara"><blockquote><p><span style="font-weight: bold">Hint</span>
|
||
|
For intertwined data definitions, create one template per data
|
||
|
definition. Create them in parallel. Make sure they refer to each other
|
||
|
in the same way the data definitions do. <span style="font-weight: bold">End</span></p></blockquote></div><div class="SIntrapara">This hint sounds more complicated than it is. For our problem, it means we
|
||
|
need three templates:
|
||
|
</div><div class="SIntrapara"><ol><li><p>one for <span class="RktSym">count</span>, which counts occurrences of symbols in <a href="part_four.html#%28tech._s._expr%29" class="techoutside" data-pltdoc="x"><span class="techinside">S-expr</span></a>s;</p></li><li><p>one for a function that counts occurrences of symbols in <a href="part_four.html#%28tech._sl%29" class="techoutside" data-pltdoc="x"><span class="techinside">SL</span></a>s; and</p></li><li><p>one for a function that counts occurrences of symbols in <a href="part_four.html#%28tech._atom%29" class="techoutside" data-pltdoc="x"><span class="techinside">Atom</span></a>s.</p></li></ol></div></p><p><div class="SIntrapara">And here are three partial templates, with conditionals as suggested by the three data definitions:
|
||
|
</div><div class="SIntrapara"><blockquote><table cellspacing="0" cellpadding="0"><tr><td align="left" valign="top"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">count</span><span class="hspace"> </span><span class="RktSym">sexp</span><span class="hspace"> </span><span class="RktSym">sy</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym">atom?</span><span class="hspace"> </span><span class="RktSym">sexp</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._else%29%29" class="RktStxLink" data-pltdoc="x">else</a></span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="RktPn">]</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">count-sl</span><span class="hspace"> </span><span class="RktSym">sl</span><span class="hspace"> </span><span class="RktSym">sy</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._empty~3f%29%29" class="RktValLink" data-pltdoc="x">empty?</a></span><span class="hspace"> </span><span class="RktSym">sl</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._else%29%29" class="RktStxLink" data-pltdoc="x">else</a></span>
|
||
|
because the data definition for <a href="part_four.html#%28tech._s._expr%29" class="techoutside" data-pltdoc="x"><span class="techinside">S-expr</span></a> has two clauses. It uses the
|
||
|
<span class="RktSym">atom?</span> function to distinguish the case for <a href="part_four.html#%28tech._atom%29" class="techoutside" data-pltdoc="x"><span class="techinside">Atom</span></a>s from the
|
||
|
case for <a href="part_four.html#%28tech._sl%29" class="techoutside" data-pltdoc="x"><span class="techinside">SL</span></a>s. The template named <span class="RktSym">count-sl</span> consumes an
|
||
|
element of <a href="part_four.html#%28tech._sl%29" class="techoutside" data-pltdoc="x"><span class="techinside">SL</span></a> and a symbol, and because <a href="part_four.html#%28tech._sl%29" class="techoutside" data-pltdoc="x"><span class="techinside">SL</span></a> is basically a
|
||
|
list, <span class="RktSym">count-sl</span> also contains a two-pronged <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span>. Finally,
|
||
|
<span class="RktSym">count-atom</span> is supposed to work for both <a href="part_four.html#%28tech._atom%29" class="techoutside" data-pltdoc="x"><span class="techinside">Atom</span></a>s and
|
||
|
<a href="i2-3.html#%28tech._symbol%29" class="techoutside" data-pltdoc="x"><span class="techinside">Symbol</span></a>s. And this means that its template checks for the three
|
||
|
distinct forms of data mentioned in the data definition of <a href="part_four.html#%28tech._atom%29" class="techoutside" data-pltdoc="x"><span class="techinside">Atom</span></a>.</div></p><p><div class="SIntrapara">The next step is to take apart compound data in the relevant clauses:
|
||
|
</div><div class="SIntrapara"><blockquote><table cellspacing="0" cellpadding="0"><tr><td align="left" valign="top"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">count</span><span class="hspace"> </span><span class="RktSym">sexp</span><span class="hspace"> </span><span class="RktSym">sy</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym">atom?</span><span class="hspace"> </span><span class="RktSym">sexp</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._else%29%29" class="RktStxLink" data-pltdoc="x">else</a></span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="RktPn">]</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">count-sl</span><span class="hspace"> </span><span class="RktSym">sl</span><span class="hspace"> </span><span class="RktSym">sy</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._empty~3f%29%29" class="RktValLink" data-pltdoc="x">empty?</a></span><span class="hspace"> </span><span class="RktSym">sl</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._else%29%29" class="RktStxLink" data-pltdoc="x">else</a></span>
|
||
|
self-references in the data definitions. In our context, this means
|
||
|
self-references <span style="font-weight: bold">and</span> references from one data definition to another
|
||
|
and (possibly) back. Let’s inspect the <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span> lines in the three
|
||
|
templates:
|
||
|
</div><div class="SIntrapara"><ol><li><p>The <span class="RktSym">atom?</span> line in <span class="RktSym">count</span> corresponds to the first
|
||
|
line in the definition of <a href="part_four.html#%28tech._s._expr%29" class="techoutside" data-pltdoc="x"><span class="techinside">S-expr</span></a>. To indicate the cross-reference
|
||
|
from here to <a href="part_four.html#%28tech._atom%29" class="techoutside" data-pltdoc="x"><span class="techinside">Atom</span></a>, we add <span class="RktPn">(</span><span class="RktSym">count-atom</span><span class="stt"> </span><span class="RktSym">sexp</span><span class="stt"> </span><span class="RktSym">sy</span><span class="RktPn">)</span>, meaning we
|
||
|
interpret <span class="RktSym">sexp</span> as an <a href="part_four.html#%28tech._atom%29" class="techoutside" data-pltdoc="x"><span class="techinside">Atom</span></a> and let the appropriate function
|
||
|
deal with it.</p></li><li><p>Following the same line of thought, the second <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span> line in
|
||
|
<span class="RktSym">count</span> calls for the addition of <span class="RktPn">(</span><span class="RktSym">count-sl</span><span class="stt"> </span><span class="RktSym">sexp</span><span class="stt"> </span><span class="RktSym">sy</span><span class="RktPn">)</span>.</p></li><li><p>The <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._empty~3f%29%29" class="RktValLink" data-pltdoc="x">empty?</a></span> line in <span class="RktSym">count-sl</span> corresponds to a line in
|
||
|
the data definition that makes no reference to another data definition.</p></li><li><p>In contrast, the <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._else%29%29" class="RktStxLink" data-pltdoc="x">else</a></span> line contains two selector expressions,
|
||
|
and each extracts a different kind of value. Specifically,
|
||
|
<span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._first%29%29" class="RktValLink" data-pltdoc="x">first</a></span><span class="stt"> </span><span class="RktSym">sl</span><span class="RktPn">)</span> is an element of <a href="part_four.html#%28tech._s._expr%29" class="techoutside" data-pltdoc="x"><span class="techinside">S-expr</span></a>, which means that we
|
||
|
wrap it in <span class="RktPn">(</span><span class="RktSym">count</span><span class="stt"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="RktPn">)</span>. After all, <span class="RktSym">count</span> is
|
||
|
responsible for counting inside of arbitrary <a href="part_four.html#%28tech._s._expr%29" class="techoutside" data-pltdoc="x"><span class="techinside">S-expr</span></a>s. Next,
|
||
|
<span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._rest%29%29" class="RktValLink" data-pltdoc="x">rest</a></span><span class="stt"> </span><span class="RktSym">sl</span><span class="RktPn">)</span> corresponds to a self-reference, and we know that
|
||
|
we need to deal with those via recursive function calls.</p></li><li><p>Finally, all three cases in <a href="part_four.html#%28tech._atom%29" class="techoutside" data-pltdoc="x"><span class="techinside">Atom</span></a> refer to atomic forms of
|
||
|
data. Therefore the <span class="RktSym">count-atom</span> function does not need to change.</p></li></ol></div></p><p><div class="SIntrapara"><a name="(idx._(gentag._502))"></a>
|
||
|
<a name="(idx._(gentag._503))"></a>
|
||
|
</div><div class="SIntrapara"><blockquote class="Figure"><blockquote class="Centerfigure"><blockquote class="FigureInside"><table cellspacing="0" cellpadding="0"><tr><td align="left" valign="top"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">count</span><span class="hspace"> </span><span class="RktSym">sexp</span><span class="hspace"> </span><span class="RktSym">sy</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym">atom?</span><span class="hspace"> </span><span class="RktSym">sexp</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">count-atom</span><span class="hspace"> </span><span class="RktSym">sexp</span><span class="hspace"> </span><span class="RktSym">sy</span><span class="RktPn">)</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._else%29%29" class="RktStxLink" data-pltdoc="x">else</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">count-sl</span><span class="hspace"> </span><span class="RktSym">sexp</span><span class="hspace"> </span><span class="RktSym">sy</span><span class="RktPn">)</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">count-sl</span><span class="hspace"> </span><span class="RktSym">sl</span><span class="hspace"> </span><span class="RktSym">sy</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._empty~3f%29%29" class="RktValLink" data-pltdoc="x">empty?</a></span><span class="hspace"> </span><span class="RktSym">sl</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermed
|
||
|
<a name="(idx._(gentag._505))"></a>
|
||
|
<a name="(idx._(gentag._506))"></a>
|
||
|
</div><div class="SIntrapara"><blockquote class="Figure"><blockquote class="Centerfigure"><blockquote class="FigureInside"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_four.html#%28tech._s._expr%29" class="techoutside" data-pltdoc="x"><span class="techinside">S-expr</span></a><span class="RktCmt"> </span><a href="i2-3.html#%28tech._symbol%29" class="techoutside" data-pltdoc="x"><span class="techinside">Symbol</span></a><span class="RktCmt"> -> </span><a href="part_two.html#%28tech._n%29" class="techoutside" data-pltdoc="x"><span class="techinside">N</span></a><span class="RktCmt"> </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">counts all occurrences of </span><span class="RktSym">sy</span><span class="RktCmt"> in </span><span class="RktSym">sexp</span><span class="RktCmt"> </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">count</span><span class="hspace"> </span><span class="RktSym">sexp</span><span class="hspace"> </span><span class="RktSym">sy</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym">atom?</span><span class="hspace"> </span><span class="RktSym">sexp</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">count-atom</span><span class="hspace"> </span><span class="RktSym">sexp</span><span class="hspace"> </span><span class="RktSym">sy</span><span class="RktPn">)</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._else%29%29" class="RktStxLink" data-pltdoc="x">else</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">count-sl</span><span class="hspace"> </span><span class="RktSym">sexp</span><span class="hspace"> </span><span class="RktSym">sy</span><span class="RktPn">)</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_four.html#%28tech._sl%29" class="techoutside" data-pltdoc="x"><span class="techinside">SL</span></a><span class="RktCmt"> </span><a href="i2-3.html#%28tech._symbol%29" class="techoutside" data-pltdoc="x"><span class="techinside">Symbol</span></a><span class="RktCmt"> -> </span><a href="part_two.html#%28tech._n%29" class="techoutside" data-pltdoc="x"><span class="techinside">N</span></a><span class="RktCmt"> </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">counts all occurrences of </span><span class="RktSym">sy</span><span class="RktCmt"> in </span><span class="RktSym">sl</span><span class="RktCmt"> </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><
|
||
|
Filling in the blanks in these templates is straightforward, as
|
||
|
<a href="part_four.html#%28counter._%28figure._fig~3asexp-function%29%29" data-pltdoc="x">figure <span class="FigureRef">117</span></a> shows. You ought to be able to explain any
|
||
|
random line in the three definitions. For example:</p><blockquote class="SCodeFlow"><p><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym">atom?</span><span class="hspace"> </span><span class="RktSym">sexp</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">count-atom</span><span class="hspace"> </span><span class="RktSym">sexp</span><span class="hspace"> </span><span class="RktSym">sy</span><span class="RktPn">)</span><span class="RktPn">]</span></p></blockquote><p> determines whether <span class="RktSym">sexp</span> is an <a href="part_four.html#%28tech._atom%29" class="techoutside" data-pltdoc="x"><span class="techinside">Atom</span></a> and, if so,
|
||
|
interprets the <a href="part_four.html#%28tech._s._expr%29" class="techoutside" data-pltdoc="x"><span class="techinside">S-expr</span></a> as an <a href="part_four.html#%28tech._atom%29" class="techoutside" data-pltdoc="x"><span class="techinside">Atom</span></a> via
|
||
|
<span class="RktSym">count-atom</span>.</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">[</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._else%29%29" class="RktStxLink" data-pltdoc="x">else</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._%2B%29%29" class="RktValLink" data-pltdoc="x">+</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">count</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._first%29%29" class="RktValLink" data-pltdoc="x">first</a></span><span class="hspace"> </span><span class="RktSym">sl</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">sy</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">count-sl</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._rest%29%29" class="RktValLink" data-pltdoc="x">rest</a></span><span class="hspace"> </span><span class="RktSym">sl</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">sy</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">]</span></td></tr></table></blockquote><p>means the given list consists of two parts: an <a href="part_four.html#%28tech._s._expr%29" class="techoutside" data-pltdoc="x"><span class="techinside">S-expr</span></a>
|
||
|
and an <a href="part_four.html#%28tech._sl%29" class="techoutside" data-pltdoc="x"><span class="techinside">SL</span></a>. By using <span class="RktSym">count</span> and <span class="RktSym">count-sl</span>, the
|
||
|
corresponding functions are used to count how often <span class="RktSym">sy</span> appears in
|
||
|
each part, and the two numbers are added up—<wbr></wbr>yielding the total number of
|
||
|
<span class="RktSym">sy</span>s in all of <span class="RktSym">sexp</span>.</p><blockquote class="SCodeFlow"><p><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._symbol~3f%29%29" class="RktValLink" data-pltdoc="x">symbol?</a></span><span class="hspace"> </span><span class="RktSym">at</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._if%29%29" class="RktStxLink" data-pltdoc="x">if</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._symbol~3d~3f%29%29" class="RktValLink" data-pltdoc="x">symbol=?</a></span><span class="hspace"> </span><span class="RktSym">at</span><span class="hspace"> </span><span class="RktSym">sy</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">1</span><span class="hspace"> </span><span class="RktVal">0</span><span class="RktPn">)</span><span class="RktPn">]</span></p></blockquote><p> tells us that if an <a href="part_four.html#%28tech._atom%29" class="techoutside" data-pltdoc="x"><span class="techinside">Atom</span></a> is a <a href="i2-3.html#%28tech._symbol%29" class="techoutside" data-pltdoc="x"><span class="techinside">Symbol</span></a>, <span class="RktSym">sy</span>
|
||
|
occurs once if it is equal to <span class="RktSym">sexp</span> and otherwise it does not
|
||
|
occur at all. Since the two pieces of data are atomic, there is no other
|
||
|
possibility.</p><p><a name="(counter._(exercise._ex~3acount-local))"></a><span style="font-weight: bold">Exercise</span> 317. A program that consists of three connected
|
||
|
functions ought to express this relationship with a <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._local%29%29" class="RktStxLink" data-pltdoc="x">local</a></span>
|
||
|
expression.</p><p>Copy and reorganize the program from <a href="part_four.html#%28counter._%28figure._fig~3asexp-function%29%29" data-pltdoc="x">figure <span class="FigureRef">117</span></a> into a
|
||
|
single function using <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._local%29%29" class="RktStxLink" data-pltdoc="x">local</a></span>. Validate the revised code with the
|
||
|
<a name="(idx._(gentag._507))"></a>test suite for <span class="RktSym">count</span>.</p><p>The second argument to the local functions, <span class="RktSym">sy</span>, never changes. It
|
||
|
is always the same as the original symbol. Hence you can eliminate it from
|
||
|
the local function definitions to tell the reader that <span class="RktSym">sy</span> is a
|
||
|
constant across the traversal process. <a href="part_four.html#%28counter._%28exercise._ex~3acount-local%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._(exercise._ex~3adepth))"></a><span style="font-weight: bold">Exercise</span> 318. Design <span class="RktSym">depth</span>. The function consumes an
|
||
|
S-expression and determines its depth. An <a href="part_four.html#%28tech._atom%29" class="techoutside" data-pltdoc="x"><span class="techinside">Atom</span></a> has a depth of
|
||
|
<span class="RktVal">1</span>. The depth of a list of S-expressions is the maximum depth of
|
||
|
its items plus <span class="RktVal">1</span>. <a href="part_four.html#%28counter._%28exercise._ex~3adepth%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._(exercise._ex~3asubstitute))"></a><span style="font-weight: bold">Exercise</span> 319. Design <span class="RktSym">substitute</span>. It
|
||
|
consumes an S-expression <span class="RktSym">s</span> and two symbols, <span class="RktSym">old</span> and
|
||
|
<span class="RktSym">new</span>. The result is like <span class="RktSym">s</span> with all occurrences of
|
||
|
<span class="RktSym">old</span> replaced by <span class="RktSym">new</span>. <a href="part_four.html#%28counter._%28exercise._ex~3asubstitute%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._(exercise._ex~3asexpr-abstract1))"></a><span style="font-weight: bold">Exercise</span> 320. Practice the step from data definition to
|
||
|
function design with two changes to the definition of <a href="part_four.html#%28tech._s._expr%29" class="techoutside" data-pltdoc="x"><span class="techinside">S-expr</span></a>.</p><p>For the first step, reformulate the data definition for <a href="part_four.html#%28tech._s._expr%29" class="techoutside" data-pltdoc="x"><span class="techinside">S-expr</span></a> so
|
||
|
that the first clause of the first data definition is expanded into the
|
||
|
three clauses of <a href="part_four.html#%28tech._atom%29" class="techoutside" data-pltdoc="x"><span class="techinside">Atom</span></a> and the second data definition uses the
|
||
|
<a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a> abstraction. Redesign the <span class="RktSym">count</span> function for this data
|
||
|
definition.</p><p>For the second step, Integrate the data definition of <a href="part_four.html#%28tech._sl%29" class="techoutside" data-pltdoc="x"><span class="techinside">SL</span></a> into the
|
||
|
one for <a href="part_four.html#%28tech._s._expr%29" class="techoutside" data-pltdoc="x"><span class="techinside">S-expr</span></a>. Simplify <span class="RktSym">count</span> again. <span style="font-weight: bold">Hint</span> Use
|
||
|
<span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._lambda%29%29" class="RktStxLink" data-pltdoc="x">lambda</a></span>. <a href="part_four.html#%28counter._%28exercise._ex~3asexpr-abstract1%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._(exercise._ex~3asexpr-abstract2))"></a><span style="font-weight: bold">Exercise</span> 321. Abstract the data definitions for
|
||
|
<a href="part_four.html#%28tech._s._expr%29" class="techoutside" data-pltdoc="x"><span class="techinside">S-expr</span></a> and <a href="part_four.html#%28tech._sl%29" class="techoutside" data-pltdoc="x"><span class="techinside">SL</span></a> so that they abstract over the kinds of <a href="part_four.html#%28tech._atom%29" class="techoutside" data-pltdoc="x"><span class="techinside">Atom</span></a>s
|
||
|
that may appear. <a href="part_four.html#%28counter._%28exercise._ex~3asexpr-abstract2%29%29" class="ex-end" data-pltdoc="x"></a></p><h4>19.4<tt> </tt><a name="(part._sec~3adesign-.N)"></a>Designing with Intertwined Data</h4><p><div class="SIntrapara">The jump from <a name="(idx._(gentag._508))"></a>self-referential data definitions to collections of
|
||
|
<a name="(idx._(gentag._509))"></a>data definitions with mutual references is far smaller than
|
||
|
the one from data definitions for finite data to self-referential data
|
||
|
definitions. Indeed, the design recipe for self-referential data
|
||
|
definitions—<wbr></wbr>see <a href="part_two.html#%28part._ch~3adesign-lists%29" data-pltdoc="x">Designing with Self-Referential Data Definitions</a>—<wbr></wbr>needs only minor adjustments
|
||
|
to apply to this seemingly complex situation:
|
||
|
</div><div class="SIntrapara"><ol><li><p>The need for “nests” of mutually related data definitions is similar
|
||
|
to the one to the need for self-referential data definitions. The problem
|
||
|
statement deals with many distinct kinds of information, and one form of
|
||
|
information refers to other kinds.</p><p>Before you proceed in such situations, draw arrows to connect references to
|
||
|
definitions. Consider the left side of
|
||
|
<a href="part_four.html#%28counter._%28figure._fig~3adef-data-mutual-arrows%29%29" data-pltdoc="x">figure <span class="FigureRef">118</span></a>. It displays the definition for
|
||
|
<a href="part_four.html#%28tech._s._expr%29" class="techoutside" data-pltdoc="x"><span class="techinside">S-expr</span></a>, which contains references to <a href="part_four.html#%28tech._sl%29" class="techoutside" data-pltdoc="x"><span class="techinside">SL</span></a> and <a href="part_four.html#%28tech._atom%29" class="techoutside" data-pltdoc="x"><span class="techinside">Atom</span></a> that
|
||
|
are connected to their respective definitions via arrows. Similarly,
|
||
|
the definition of <a href="part_four.html#%28tech._sl%29" class="techoutside" data-pltdoc="x"><span class="techinside">SL</span></a> contains one self-reference and one reference
|
||
|
back to <a href="part_four.html#%28tech._s._expr%29" class="techoutside" data-pltdoc="x"><span class="techinside">S-expr</span></a>; again, both are connected by appropriate arrows.</p><p>Like self-referential data definitions, these nests of definitions also
|
||
|
call for validation. At a minimum, you must be able to construct some
|
||
|
examples for every individual definition. Start from clauses that do not
|
||
|
refer to any of the other data definitions in the nest. Keep in mind that
|
||
|
the definition may be invalid if it is impossible to generate examples
|
||
|
from them.</p></li><li><p>The key change is that you must design as many functions in parallel
|
||
|
as there are data definitions. Each function specializes for one of the
|
||
|
data definitions; all remaining arguments remain the same. Based on that,
|
||
|
you start with a signature, a purpose statement, and a dummy definition
|
||
|
<span style="font-weight: bold">for each function</span>.</p></li><li><p>Be sure to work through functional examples that use all mutual
|
||
|
references in the nest of data definitions.</p></li><li><p>For each function, design the template according to its primary data
|
||
|
definition. Use <a href="part_two.html#%28counter._%28figure._fig~3atemplate-q%29%29" data-pltdoc="x">figure <span class="FigureRef">52</span></a> to guide the template creation
|
||
|
up to the last step. The revised last step calls for a check for all
|
||
|
self-references and cross-references. Use the data definitions annotated
|
||
|
with arrows to guide this step. For each arrow in the data definitions,
|
||
|
include an arrow in the templates. See the right side of
|
||
|
<a href="part_four.html#%28counter._%28figure._fig~3adef-data-mutual-arrows%29%29" data-pltdoc="x">figure <span class="FigureRef">118</span></a> for the arrow-annotated version of
|
||
|
the templates.</p><blockquote class="Herefigure"><blockquote class="Centerfigure"><blockquote class="FigureInside"><blockquote class="SVInsetFlow"><table cellspacing="0" cellpadding="0"><tr><td valign="top"><p><img style="vertical-align: -0.0px; margin: -3px -3px -3px -3px;" src="pict_141.png" alt="image" width="156.888671875" height="304.328125"/></p></td><td valign="top"><p><span class="hspace"> </span></p></td><td valign="top"><p><img style="vertical-align: -0.0px; margin: -3px -3px -3px -3px;" src="pict_142.png" alt="image" width="235.99609375" height="304.328125"/></p></td></tr></table></blockquote></blockquote></blockquote><p class="Centertext"><span class="Legend"><span class="FigureTarget"><a name="(counter._(figure._fig~3adef-data-mutual-arrows))" x-target-lift="Figure"></a>Figure 118: </span>Arrows for nests of data definitions and templates</span></p></blockquote><p>Now replace the arrows with actual function calls. As you gain
|
||
|
experience, you will naturally skip the arrow-drawing step and use
|
||
|
function calls directly.</p><p><span style="font-weight: bold">Note</span> Observe how both nests—<wbr></wbr>the one for data definitions and the one
|
||
|
for function templates—<wbr></wbr>contain four arrows, and note how pairs of arrows
|
||
|
correspond to each other. Researchers call this correspondence a
|
||
|
<span style="font-style: italic">symmetry</span>. It is evidence that the design recipe provides a
|
||
|
natural way for going from problems to solutions.</p></li><li><p>For the design of the body, we start with those <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span> lines
|
||
|
that do not contain natural recursions or calls to other functions. They
|
||
|
are called <span style="font-style: italic">base cases</span>. The corresponding answers are typically
|
||
|
easy to formulate or are already given by the examples. After that, you
|
||
|
deal with the self-referential cases and the cases of cross-function
|
||
|
calls. Let the questions and answers of <a href="part_two.html#%28counter._%28figure._fig~3adefinition-q%29%29" data-pltdoc="x">figure <span class="FigureRef">53</span></a> guide
|
||
|
you.</p></li><li><p>Run the tests when all definitions are completed. If an auxiliary
|
||
|
function is broken, you may get two error reports, one for the main
|
||
|
function and another one for the flawed auxiliary definition. A
|
||
|
<span style="font-weight: bold">single</span> fix should eliminate both. Do make sure that running the
|
||
|
tests covers all the pieces of the function.</p></li></ol></div><div class="SIntrapara">Finally, if you are stuck in step 5, remember the table-based approach to
|
||
|
guessing the combination function. In the case of intertwined data, you may
|
||
|
need not only a table per case but also a table per case and per function to
|
||
|
work out the combination.</div></p><h4>19.5<tt> </tt><a name="(part._sec~3aproj-bst)"></a>Project: BSTs</h4><p>Programmers often work with tree representations of data to improve the
|
||
|
performance of their functions. A particularly well-known form of tree is the
|
||
|
<span style="font-weight: bold">binary search tree</span> because it is a good way to store and retrieve
|
||
|
information quickly.</p><p><div class="SIntrapara">To be concrete, let’s discuss binary trees that manage information about
|
||
|
people. Instead of the <span class="RktSym">child</span><span class="RktMeta"></span> structures in family trees, a binary
|
||
|
tree contains <span class="RktSym">node</span><span class="RktMeta"></span>s:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define-struct%29%29" class="RktStxLink" data-pltdoc="x">define-struct</a></span><span class="hspace"> </span><span class="RktSym">no-info</span><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">]</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">NONE</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">make-no-info</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define-struct%29%29" class="RktStxLink" data-pltdoc="x">define-struct</a></span><span class="hspace"> </span><span class="RktSym">node</span><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym">ssn</span><span class="hspace"> </span><span class="RktSym">name</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/teachpack/2htdpuniverse.html#%28form._world._%28%28lib._2htdp%2Funiverse..rkt%29._left%29%29" class="RktStxLink" data-pltdoc="x">left</a></span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/teachpack/2htdpuniverse.html#%28form._world._%28%28lib._2htdp%2Funiverse..rkt%29._right%29%29" class="RktStxLink" data-pltdoc="x">right</a></span><span class="RktPn">]</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">A </span><a name="(tech._bt)"></a><span style="font-style: italic">BT</span><span class="RktCmt"> (short for </span><a name="(tech._binarytree)"></a><span style="font-style: italic">BinaryTree</span><span class="RktCmt">) is one of:</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">–</span><span class="RktCmt"> </span><span class="RktSym">NONE</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">–</span><span class="RktCmt"> </span><span class="RktPn">(</span><span class="RktSym">make-node</span><span class="stt"> </span><a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a><span class="stt"> </span><a href="i2-3.html#%28tech._symbol%29" class="techoutside" data-pltdoc="x"><span class="techinside">Symbol</span></a><span class="stt"> </span><a href="part_four.html#%28tech._bt%29" class="techoutside" data-pltdoc="x"><span class="techinside">BT</span></a><span class="stt"> </span><a href="part_four.html#%28tech._bt%29" class="techoutside" data-pltdoc="x"><span class="techinside">BT</span></a><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">The corresponding data definition is like the one for family trees with
|
||
|
<span class="RktSym">NONE</span><span class="RktMeta"></span> indicating a lack of information and each <span class="RktSym">node</span>
|
||
|
recording a social security number, a name, and two other binary
|
||
|
trees. The latter are like the parents of family trees,
|
||
|
though the relationship between a <span class="RktSym">node</span><span class="RktMeta"></span> and its <span class="RktSym"><a href="https://docs.racket-lang.org/teachpack/2htdpuniverse.html#%28form._world._%28%28lib._2htdp%2Funiverse..rkt%29._left%29%29" class="RktStxLink" data-pltdoc="x">left</a></span><span class="RktMeta"></span> and
|
||
|
<span class="RktSym"><a href="https://docs.racket-lang.org/teachpack/2htdpuniverse.html#%28form._world._%28%28lib._2htdp%2Funiverse..rkt%29._right%29%29" class="RktStxLink" data-pltdoc="x">right</a></span><span class="RktMeta"></span> trees is not based on family relationships.</div></p><p><div class="SIntrapara">Here are two binary trees:
|
||
|
</div><div class="SIntrapara"><blockquote><table cellspacing="0" cellpadding="0"><tr><td><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym">make-node</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">15</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">d</span></td></tr><tr><td><span class="hspace"> </span><span class="RktSym">NONE</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">make-node</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">24</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">i</span><span class="hspace"> </span><span class="RktSym">NONE</span><span class="hspace"> </span><span class="RktSym">NONE</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></td><td><p><span class="hspace"> </span></p></td><td><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym">make-node</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">15</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">d</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">make-node</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">87</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">h</span><span class="hspace"> </span><span class="RktSym">NONE</span><span class="hspace"> </span><span class="RktSym">NONE</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktSym">NONE</span><span class="RktPn">)</span></td></tr></table></td></tr></table></blockquote></div></p><p><a href="part_four.html#%28counter._%28figure._fig~3abst%29%29" data-pltdoc="x">Figure <span class="FigureRef">119</span></a> shows how we should think about such trees as
|
||
|
drawings. The trees are drawn upside down, with the root at the top and the
|
||
|
crown of the tree at the bottom. Each circle corresponds to a node, labeled
|
||
|
with the <span class="RktSym">ssn</span><span class="RktMeta"></span> field of a corresponding <span class="RktSym">node</span><span class="RktMeta"></span> structure. The
|
||
|
drawings omit <span class="RktSym">NONE</span><span class="RktMeta"></span>.</p><blockquote class="Herefigure"><blockquote class="Centerfigure"><blockquote class="FigureInside"><blockquote class="SCentered"><table cellspacing="0" cellpadding="0"><tr><td><p>tree A</p></td><td><p><span class="hspace"> </span></p></td><td><p>tree B</p></td></tr><tr><td><p></p></td><td><p><span class="hspace"> </span></p></td><td><p></p></td></tr><tr><td><p><img style="vertical-align: 0px; margin: -3px -3px -3px -3px;" src="pict_143.png" alt="image" width="289.0" height="209.0"/></p></td><td><p><span class="hspace"> </span></p></td><td><p><img style="vertical-align: 0px; margin: -3px -3px -3px -3px;" src="pict_144.png" alt="image" width="289.0" height="209.0"/></p></td></tr></table></blockquote></blockquote></blockquote><p class="Centertext"><span class="Legend"><span class="FigureTarget"><a name="(counter._(figure._fig~3abst))" x-target-lift="Figure"></a>Figure 119: </span>A binary search tree and a binary tree</span></p></blockquote><p><a name="(counter._(exercise._ex~3abst1))"></a><span style="font-weight: bold">Exercise</span> 322. Draw the above two trees in the manner of
|
||
|
<a href="part_four.html#%28counter._%28figure._fig~3abst%29%29" data-pltdoc="x">figure <span class="FigureRef">119</span></a>. Then design <span class="RktSym">contains-bt?</span><span class="RktMeta"></span>, which determines
|
||
|
whether a given number occurs in some given <span class="RktSym">BT</span>. <a href="part_four.html#%28counter._%28exercise._ex~3abst1%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._(exercise._ex~3abst1-search))"></a><span style="font-weight: bold">Exercise</span> 323. Design <span class="RktSym">search-bt</span><span class="RktMeta"></span>. The function consumes
|
||
|
a number <span class="RktSym">n</span><span class="RktMeta"></span> and a <span class="RktSym">BT</span><span class="RktMeta"></span>. If the tree contains a <span class="RktSym">node</span><span class="RktMeta"></span>
|
||
|
structure whose <span class="RktSym">ssn</span><span class="RktMeta"></span> field is <span class="RktSym">n</span><span class="RktMeta"></span>, the function produces the
|
||
|
value of the <span class="RktSym"><a href="https://docs.racket-lang.org/teachpack/2htdpuniverse.html#%28form._world._%28%28lib._2htdp%2Funiverse..rkt%29._name%29%29" class="RktStxLink" data-pltdoc="x">name</a></span><span class="RktMeta"></span> field in that node. Otherwise, the function
|
||
|
produces <span class="RktVal">#false</span><span class="RktMeta"></span>.</p><p><span style="font-weight: bold">Hint</span> Consider using <span class="RktSym">contains-bt?</span><span class="RktMeta"></span> to check the entire tree
|
||
|
first or <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._boolean~3f%29%29" class="RktValLink" data-pltdoc="x">boolean?</a></span> to check the result of the natural recursion at
|
||
|
each stage. <a href="part_four.html#%28counter._%28exercise._ex~3abst1-search%29%29" class="ex-end" data-pltdoc="x"></a></p><p><div class="SIntrapara">If we read the numbers in the two trees in <a href="part_four.html#%28counter._%28figure._fig~3abst%29%29" data-pltdoc="x">figure <span class="FigureRef">119</span></a> from left
|
||
|
to right, we obtain two different sequences:
|
||
|
</div><div class="SIntrapara"><blockquote><table cellspacing="0" cellpadding="0"><tr><td align="left"><p>tree A</p></td><td align="left"><p><span class="hspace"> </span></p></td><td align="center"><p>10</p></td><td align="center"><p><span class="hspace"> </span></p></td><td align="center"><p>15</p></td><td align="center"><p><span class="hspace"> </span></p></td><td align="center"><p>24</p></td><td align="center"><p><span class="hspace"> </span></p></td><td align="center"><p>29</p></td><td align="center"><p><span class="hspace"> </span></p></td><td align="center"><p>63</p></td><td align="center"><p><span class="hspace"> </span></p></td><td align="center"><p>77</p></td><td align="center"><p><span class="hspace"> </span></p></td><td align="center"><p>89</p></td><td align="center"><p><span class="hspace"> </span></p></td><td align="center"><p>95</p></td><td align="center"><p><span class="hspace"> </span></p></td><td align="center"><p>99</p></td></tr><tr><td align="left"><p>tree B</p></td><td align="left"><p><span class="hspace"> </span></p></td><td align="center"><p>87</p></td><td align="center"><p><span class="hspace"> </span></p></td><td align="center"><p>15</p></td><td align="center"><p><span class="hspace"> </span></p></td><td align="center"><p>24</p></td><td align="center"><p><span class="hspace"> </span></p></td><td align="center"><p>29</p></td><td align="center"><p><span class="hspace"> </span></p></td><td align="center"><p>63</p></td><td align="center"><p><span class="hspace"> </span></p></td><td align="center"><p>33</p></td><td align="center"><p><span class="hspace"> </span></p></td><td align="center"><p>89</p></td><td align="center"><p><span class="hspace"> </span></p></td><td align="center"><p>95</p></td><td align="center"><p><span class="hspace"> </span></p></td><td align="center"><p>99</p></td></tr></table></blockquote></div><div class="SIntrapara">The sequence for tree A is sorted in ascending order the one for B is
|
||
|
not. A binary tree of the first kind is a <span style="font-weight: bold">binary search
|
||
|
tree</span>. Every binary search tree is a binary tree, but not every binary
|
||
|
tree is a binary search tree. More concretely, we formulate a
|
||
|
condition—<wbr></wbr>or data invariant—<wbr></wbr>that distinguishes a binary search tree
|
||
|
from a binary tree:</div></p><p><span style="font-weight: bold">The BST Invariant</span></p><p><div class="SIntrapara"><blockquote><p><div class="SIntrapara">A <a name="(tech._bst)"></a><span style="font-style: italic">BST</span> (short for <a name="(tech._binary._search._tree)"></a><span style="font-style: italic">binary search tree</span>) is a <a href="part_four.html#%28tech._bt%29" class="techoutside" data-pltdoc="x"><span class="techinside">BT</span></a>
|
||
|
according to the following conditions:
|
||
|
</div><div class="SIntrapara"><ul><li><p><span class="RktSym">NONE</span> is always a <a href="part_four.html#%28tech._bst%29" class="techoutside" data-pltdoc="x"><span class="techinside">BST</span></a>.</p></li><li><p><div class="SIntrapara"><span class="RktPn">(</span><span class="RktSym">make-node</span><span class="stt"> </span><span class="RktSym">ssn0</span><span class="stt"> </span><span class="RktSym">name0</span><span class="stt"> </span><span class="RktSym">L</span><span class="stt"> </span><span class="RktSym">R</span><span class="RktPn">)</span> is a <a href="part_four.html#%28tech._bst%29" class="techoutside" data-pltdoc="x"><span class="techinside">BST</span></a> if
|
||
|
</div><div class="SIntrapara"><ul><li><p><span class="RktSym">L</span> is a <a href="part_four.html#%28tech._bst%29" class="techoutside" data-pltdoc="x"><span class="techinside">BST</span></a>,</p></li><li><p><span class="RktSym">R</span> is a <a href="part_four.html#%28tech._bst%29" class="techoutside" data-pltdoc="x"><span class="techinside">BST</span></a>,</p></li><li><p>all <span class="RktSym">ssn</span> fields in <span class="RktSym">L</span> are smaller than <span class="RktSym">ssn0</span>,</p></li><li><p>all <span class="RktSym">ssn</span> fields in <span class="RktSym">R</span> are larger than <span class="RktSym">ssn0</span>.</p></li></ul></div></p></li></ul></div></p></blockquote></div><div class="SIntrapara">In other words, to check whether a <a href="part_four.html#%28tech._bt%29" class="techoutside" data-pltdoc="x"><span class="techinside">BT</span></a> also belongs to <a href="part_four.html#%28tech._bst%29" class="techoutside" data-pltdoc="x"><span class="techinside">BST</span></a>,
|
||
|
we must inspect all numbers in all subtrees and ensure that they are
|
||
|
smaller or larger than some given number. This places an additional burden
|
||
|
on the construction of data, but, as the following exercises show,
|
||
|
it is well worth it.</div></p><p><a name="(counter._(exercise._ex~3abst0))"></a><span style="font-weight: bold">Exercise</span> 324. Design the function <span class="RktSym">inorder</span><span class="RktMeta"></span>. It consumes a
|
||
|
binary tree and produces the sequence of all the <span class="RktSym">ssn</span><span class="RktMeta"></span> numbers in the
|
||
|
tree as they show up from left to right when looking at a tree drawing.</p><p><div class="SIntrapara"><span style="font-weight: bold">Hint</span> Use <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._append%29%29" class="RktValLink" data-pltdoc="x">append</a></span><span class="RktMeta"></span>, which concatenates lists like thus:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._append%29%29" class="RktValLink" data-pltdoc="x">append</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">1</span><span class="hspace"> </span><span class="RktVal">2</span><span class="hspace"> </span><span class="RktVal">3</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">4</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">5</span><span class="hspace"> </span><span class="RktVal">6</span><span class="hspace"> </span><span class="RktVal">7</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktSym">==</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">1</span><span class="hspace"> </span><span class="RktVal">2</span><span class="hspace"> </span><span class="RktVal">3</span><span class="hspace"> </span><span class="RktVal">4</span><span class="hspace"> </span><span class="RktVal">5</span><span class="hspace"> </span><span class="RktVal">6</span><span class="hspace"> </span><span class="RktVal">7</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">What does <span class="RktSym">inorder</span><span class="RktMeta"></span> produce for a binary search tree? <a href="part_four.html#%28counter._%28exercise._ex~3abst0%29%29" class="ex-end" data-pltdoc="x"></a></div></p><p>Looking for a <span class="RktSym">node</span><span class="RktMeta"></span> with a given <span class="RktSym">ssn</span> in a <span class="RktSym">BST</span><span class="RktMeta"></span> may
|
||
|
exploit the <a href="part_four.html#%28tech._bst%29" class="techoutside" data-pltdoc="x"><span class="techinside">BST</span></a> invariant. To find out whether a <span class="RktSym">BT</span><span class="RktMeta"></span> contains
|
||
|
a node with a specific <span class="RktSym">ssn</span><span class="RktMeta"></span>, a function may have to look at
|
||
|
every <span class="RktSym">node</span><span class="RktMeta"></span> of the tree. In contrast, to find out whether a binary
|
||
|
<span style="font-weight: bold">search</span> tree contains the same <span class="RktSym">ssn</span>, a function may eliminate
|
||
|
one of two subtrees for every node it inspects.</p><p><div class="SIntrapara">Let’s illustrate the idea with this sample <span class="RktSym">BST</span><span class="RktMeta"></span>:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktPn">(</span><span class="RktSym">make-node</span><span class="hspace"> </span><span class="RktVal">66</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">a</span><span class="hspace"> </span><span class="RktSym">L</span><span class="hspace"> </span><span class="RktSym">R</span><span class="RktPn">)</span></p></blockquote></div><div class="SIntrapara">If we are looking for <span class="RktVal">66</span><span class="RktMeta"></span>, we have found the node we are looking
|
||
|
for. Now, if we are looking for a smaller number, say <span class="RktVal">63</span><span class="RktMeta"></span>, we can
|
||
|
focus the search on <span class="RktSym">L</span><span class="RktMeta"></span> because <span style="font-weight: bold">all</span> <span class="RktSym">node</span><span class="RktMeta"></span>s with
|
||
|
<span class="RktSym">ssn</span><span class="RktMeta"></span> fields smaller than <span class="RktVal">66</span><span class="RktMeta"></span> are in <span class="RktSym">L</span><span class="RktMeta"></span>. Similarly, if we
|
||
|
were to look for <span class="RktVal">99</span><span class="RktMeta"></span>, we would ignore <span class="RktSym">L</span><span class="RktMeta"></span> and focus on <span class="RktSym">R</span><span class="RktMeta"></span>
|
||
|
because <span style="font-weight: bold">all</span> <span class="RktSym">node</span><span class="RktMeta"></span>s with <span class="RktSym">ssn</span><span class="RktMeta"></span>s larger than <span class="RktVal">66</span><span class="RktMeta"></span> are
|
||
|
in <span class="RktSym">R</span><span class="RktMeta"></span>.</div></p><p><a name="(counter._(exercise._ex~3abst2))"></a><span style="font-weight: bold">Exercise</span> 325. Design <span class="RktSym">search-bst</span><span class="RktMeta"></span>. The function consumes a
|
||
|
number <span class="RktSym">n</span><span class="RktMeta"></span> and a <span class="RktSym">BST</span><span class="RktMeta"></span>. If the tree contains a <span class="RktSym">node</span><span class="RktMeta"></span> whose
|
||
|
<span class="RktSym">ssn</span><span class="RktMeta"></span> field is <span class="RktSym">n</span><span class="RktMeta"></span>, the function produces the value of the
|
||
|
<span class="RktSym"><a href="https://docs.racket-lang.org/teachpack/2htdpuniverse.html#%28form._world._%28%28lib._2htdp%2Funiverse..rkt%29._name%29%29" class="RktStxLink" data-pltdoc="x">name</a></span><span class="RktMeta"></span> field in that node. Otherwise, the function produces
|
||
|
<span class="RktSym">NONE</span><span class="RktMeta"></span>. The function organization must exploit the BST invariant so
|
||
|
that the function performs as few comparisons as necessary.</p><p>See <a href="part_two.html#%28counter._%28exercise._ex~3asort2%29%29" data-pltdoc="x">exercise 189</a> for searching in sorted lists. Compare! <a href="part_four.html#%28counter._%28exercise._ex~3abst2%29%29" class="ex-end" data-pltdoc="x"></a></p><p>Building a binary tree is easy; building a binary search tree is
|
||
|
complicated. Given any two <a href="part_four.html#%28tech._bt%29" class="techoutside" data-pltdoc="x"><span class="techinside">BT</span></a>s, a number, and a name, we simply
|
||
|
apply <span class="RktSym">make-node</span> to these values in the correct order, and voilà,
|
||
|
we get a new <a href="part_four.html#%28tech._bt%29" class="techoutside" data-pltdoc="x"><span class="techinside">BT</span></a>. This same procedure fails for <a href="part_four.html#%28tech._bst%29" class="techoutside" data-pltdoc="x"><span class="techinside">BST</span></a>s because
|
||
|
the result would typically not be a <span class="RktSym">BST</span><span class="RktMeta"></span>. For example, if one
|
||
|
<a href="part_four.html#%28tech._bst%29" class="techoutside" data-pltdoc="x"><span class="techinside">BST</span></a> contains nodes with <span class="RktSym">ssn</span> fields <span class="RktVal">3</span><span class="RktMeta"></span> and <span class="RktVal">5</span><span class="RktMeta"></span>
|
||
|
in the correct order, and the other one contains <span class="RktSym">ssn</span> fields
|
||
|
<span class="RktVal">2</span><span class="RktMeta"></span> and <span class="RktVal">6</span><span class="RktMeta"></span>, simply combining the two trees with another social
|
||
|
security number and a name does not produce a <a href="part_four.html#%28tech._bst%29" class="techoutside" data-pltdoc="x"><span class="techinside">BST</span></a>.</p><p>The remaining two exercises explain how to build a <a href="part_four.html#%28tech._bst%29" class="techoutside" data-pltdoc="x"><span class="techinside">BST</span></a> from a list
|
||
|
of numbers and names. Specifically, the first exercise calls for a
|
||
|
function that inserts a given <span class="RktSym">ssn0</span> and <span class="RktSym">name0</span> into a
|
||
|
<a href="part_four.html#%28tech._bst%29" class="techoutside" data-pltdoc="x"><span class="techinside">BST</span></a>; that is, it produces a <a href="part_four.html#%28tech._bst%29" class="techoutside" data-pltdoc="x"><span class="techinside">BST</span></a> like the one it is given
|
||
|
with one more node inserted containing <span class="RktSym">ssn0</span>, <span class="RktSym">name0</span>, and
|
||
|
<span class="RktSym">NONE</span> subtrees. The second exercise then requests a function that
|
||
|
can deal with a complete list of numbers and names.</p><p><div class="SIntrapara"><a name="(counter._(exercise._ex~3abst3))"></a><span style="font-weight: bold">Exercise</span> 326. Design the function <span class="RktSym">create-bst</span><span class="RktMeta"></span>. It consumes a
|
||
|
<span class="RktSym">BST</span><span class="RktMeta"></span> <span class="RktSym">B</span><span class="RktMeta"></span>, a number <span class="RktSym">N</span><span class="RktMeta"></span>, and a symbol <span class="RktSym">S</span><span class="RktMeta"></span>. It produces
|
||
|
a <span class="RktSym">BST</span><span class="RktMeta"></span> that is just like <span class="RktSym">B</span><span class="RktMeta"></span> and that in place of one
|
||
|
<span class="RktSym">NONE</span><span class="RktMeta"></span> subtree contains the <span class="RktSym">node</span><span class="RktMeta"></span> structure
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktPn">(</span><span class="RktSym">make-node</span><span class="hspace"> </span><span class="RktSym">N</span><span class="hspace"> </span><span class="RktSym">S</span><span class="hspace"> </span><span class="RktSym">NONE</span><span class="hspace"> </span><span class="RktSym">NONE</span><span class="RktPn">)</span></p></blockquote></div><div class="SIntrapara">Once the design is completed, use the function on tree A from <a href="part_four.html#%28counter._%28figure._fig~3abst%29%29" data-pltdoc="x">figure <span class="FigureRef">119</span></a>. <a href="part_four.html#%28counter._%28exercise._ex~3abst3%29%29" class="ex-end" data-pltdoc="x"></a></div></p><p><div class="SIntrapara"><a name="(counter._(exercise._ex~3abst4))"></a><span style="font-weight: bold">Exercise</span> 327. Design the function <span class="RktSym">create-bst-from-list</span><span class="RktMeta"></span>. It
|
||
|
consumes a list of numbers and names and produces a <a href="part_four.html#%28tech._bst%29" class="techoutside" data-pltdoc="x"><span class="techinside">BST</span></a> by
|
||
|
repeatedly applying <span class="RktSym">create-bst</span>. Here is the signature:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">[</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> [</span><a href="part_three.html#%28tech._sim-dd._list%29" class="techoutside" data-pltdoc="x"><span class="techinside">List</span></a><span class="RktCmt"> Number Symbol]] -> </span><a href="part_four.html#%28tech._bst%29" class="techoutside" data-pltdoc="x"><span class="techinside">BST</span></a></p></blockquote></div><div class="SIntrapara">Use the complete function to create a <a href="part_four.html#%28tech._bst%29" class="techoutside" data-pltdoc="x"><span class="techinside">BST</span></a> from this sample input:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">(</span><span class="RktVal">99</span><span class="hspace"> </span><span class="RktVal">o</span><span class="RktVal">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">77</span><span class="hspace"> </span><span class="RktVal">l</span><span class="RktVal">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">24</span><span class="hspace"> </span><span class="RktVal">i</span><span class="RktVal">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">10</span><span class="hspace"> </span><span class="RktVal">h</span><span class="RktVal">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">95</span><span class="hspace"> </span><span class="RktVal">g</span><span class="RktVal">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">15</span><span class="hspace"> </span><span class="RktVal">d</span><span class="RktVal">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">89</span><span class="hspace"> </span><span class="RktVal">c</span><span class="RktVal">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">29</span><span class="hspace"> </span><span class="RktVal">b</span><span class="RktVal">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">63</span><span class="hspace"> </span><span class="RktVal">a</span><span class="RktVal">)</span><span class="RktVal">)</span></td></tr></table></blockquote></div><div class="SIntrapara">The result is tree A in <a href="part_four.html#%28counter._%28figure._fig~3abst%29%29" data-pltdoc="x">figure <span class="FigureRef">119</span></a>, if you follow the <a name="(idx._(gentag._510))"></a>structural
|
||
|
design recipe. If you use an existing abstraction, you may still get this
|
||
|
tree but you may also get an “inverted” one. Why? <a href="part_four.html#%28counter._%28exercise._ex~3abst4%29%29" class="ex-end" data-pltdoc="x"></a></div></p><h4>19.6<tt> </tt><a name="(part._sec~3asimplification)"></a>Simplifying Functions</h4><p><a href="part_four.html#%28counter._%28exercise._ex~3acount-local%29%29" data-pltdoc="x">Exercise 317</a> shows how to use <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._local%29%29" class="RktStxLink" data-pltdoc="x">local</a></span> to organize a
|
||
|
function that deals with an intertwined form of data. This organization
|
||
|
also helps simplify functions once we know that the data definition is
|
||
|
final. To demonstrate this point, we explain how to simplify the solution
|
||
|
of <a href="part_four.html#%28counter._%28exercise._ex~3asubstitute%29%29" data-pltdoc="x">exercise 319</a>.</p><p><div class="SIntrapara"><a name="(idx._(gentag._511))"></a>
|
||
|
</div><div class="SIntrapara"><blockquote class="Figure"><blockquote class="Centerfigure"><blockquote class="FigureInside"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_four.html#%28tech._s._expr%29" class="techoutside" data-pltdoc="x"><span class="techinside">S-expr</span></a><span class="RktCmt"> </span><a href="i2-3.html#%28tech._symbol%29" class="techoutside" data-pltdoc="x"><span class="techinside">Symbol</span></a><span class="RktCmt"> </span><a href="part_four.html#%28tech._atom%29" class="techoutside" data-pltdoc="x"><span class="techinside">Atom</span></a><span class="RktCmt"> -> </span><a href="part_four.html#%28tech._s._expr%29" class="techoutside" data-pltdoc="x"><span class="techinside">S-expr</span></a></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">replaces all occurrences of </span><span class="RktSym">old</span><span class="RktCmt"> in </span><span class="RktSym">sexp</span><span class="RktCmt"> with </span><span class="RktSym">new</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._check-expect%29%29" class="RktStxLink" data-pltdoc="x">check-expect</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">substitute</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">(</span><span class="RktVal">(</span><span class="RktVal">world</span><span class="RktVal">)</span><span class="hspace"> </span><span class="RktVal">bye</span><span class="RktVal">)</span><span class="hspace"> </span><span class="RktVal">bye</span><span class="RktVal">)</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">bye</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">42</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">(</span><span class="RktVal">(</span><span class="RktVal">world</span><span class="RktVal">)</span><span class="hspace"> </span><span class="RktVal">42</span><span class="RktVal">)</span><span class="hspace"> </span><span class="RktVal">42</span><span class="RktVal">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">substitute</span><span class="hspace"> </span><span class="RktSym">sexp</span><span class="hspace"> </span><span class="RktSym">old</span><span class="hspace"> </span><span class="RktSym">new</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._local%29%29" class="RktStxLink" data-pltdoc="x">local</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_four.html#%28tech._s._expr%29" class="techoutside" data-pltdoc="x"><span class="techinside">S-expr</span></a><span class="RktCmt"> -> </span><a href="part_four.html#%28tech._s._expr%29" class="techoutside" data-pltdoc="x"><span class="techinside">S-expr</span></a></td></tr><tr><td><span class="hspace"> &nb
|
||
|
<span class="RktSym">substitute</span> function. The definition uses <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._local%29%29" class="RktStxLink" data-pltdoc="x">local</a></span> and three
|
||
|
auxiliary functions as suggested by the data definition. The figure
|
||
|
includes a test case so that you can retest the function after each edit
|
||
|
suggested below. Stop! Develop additional test cases; one is almost never
|
||
|
enough.</p><p><a name="(counter._(exercise._ex~3asimplify1))"></a><span style="font-weight: bold">Exercise</span> 328. Copy and paste <a href="part_four.html#%28counter._%28figure._fig~3asimplifying1%29%29" data-pltdoc="x">figure <span class="FigureRef">120</span></a> into
|
||
|
DrRacket; include your test suite. Validate the test suite. As you read along
|
||
|
the remainder of this section, perform the edits and rerun the test suites
|
||
|
to confirm the validity of our arguments. <a href="part_four.html#%28counter._%28exercise._ex~3asimplify1%29%29" class="ex-end" data-pltdoc="x"></a></p><p><div class="SIntrapara"><a name="(idx._(gentag._512))"></a>
|
||
|
</div><div class="SIntrapara"><blockquote class="Figure"><blockquote class="Centerfigure"><blockquote class="FigureInside"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">substitute</span><span class="hspace"> </span><span class="RktSym">sexp</span><span class="hspace"> </span><span class="RktSym">old</span><span class="hspace"> </span><span class="RktSym">new</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._local%29%29" class="RktStxLink" data-pltdoc="x">local</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_four.html#%28tech._s._expr%29" class="techoutside" data-pltdoc="x"><span class="techinside">S-expr</span></a><span class="RktCmt"> -> </span><a href="part_four.html#%28tech._s._expr%29" class="techoutside" data-pltdoc="x"><span class="techinside">S-expr</span></a></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">for-sexp</span><span class="hspace"> </span><span class="RktSym">sexp</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym">atom?</span><span class="hspace"> </span><span class="RktSym">sexp</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">for-atom</span><span class="hspace"> </span><span class="RktSym">sexp</span><span class="RktPn">)</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._else%29%29" class="RktStxLink" data-pltdoc="x">else</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">for-sl</span><span class="hspace"> </span><span class="RktSym">sexp</span><span class="RktPn">)</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_four.html#%28tech._sl%29" class="techoutside" data-pltdoc="x"><span class="techinside">SL</span></a><span class="RktCmt"> -> </span><a href="part_four.html#%28tech._s._expr%29" class="techoutside" data-pltdoc="x"><span class="techinside">S-expr</span></a><span class="RktCmt"> </span></td></tr><tr><td><span class="hspace">  
|
||
|
<span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._map%29%29" class="RktValLink" data-pltdoc="x">map</a></span> to simplify <span class="RktSym">for-sl</span>. See
|
||
|
<a href="part_four.html#%28counter._%28figure._fig~3asimplifying2%29%29" data-pltdoc="x">figure <span class="FigureRef">121</span></a> for the result. While the original program
|
||
|
says that <span class="RktSym">for-sexp</span> is applied to every item on <span class="RktSym">sl</span>, its
|
||
|
revised definition expresses the same idea more succinctly with
|
||
|
<span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._map%29%29" class="RktValLink" data-pltdoc="x">map</a></span>.</p><p>For the second simplification step, we need to remind you that
|
||
|
<span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._equal~3f%29%29" class="RktValLink" data-pltdoc="x">equal?</a></span> compares two arbitrary values. With this in mind, the
|
||
|
third <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._local%29%29" class="RktStxLink" data-pltdoc="x">local</a></span> function becomes a
|
||
|
one-liner. <a href="part_four.html#%28counter._%28figure._fig~3asimplifying3%29%29" data-pltdoc="x">Figure <span class="FigureRef">122</span></a> displays this second
|
||
|
simplification.</p><p><div class="SIntrapara"><a name="(idx._(gentag._513))"></a>
|
||
|
<a name="(idx._(gentag._514))"></a>
|
||
|
</div><div class="SIntrapara"><blockquote class="Figure"><blockquote class="Centerfigure"><blockquote class="FigureInside"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">substitute</span><span class="hspace"> </span><span class="RktSym">sexp</span><span class="hspace"> </span><span class="RktSym">old</span><span class="hspace"> </span><span class="RktSym">new</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._local%29%29" class="RktStxLink" data-pltdoc="x">local</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_four.html#%28tech._s._expr%29" class="techoutside" data-pltdoc="x"><span class="techinside">S-expr</span></a><span class="RktCmt"> -> </span><a href="part_four.html#%28tech._s._expr%29" class="techoutside" data-pltdoc="x"><span class="techinside">S-expr</span></a></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">for-sexp</span><span class="hspace"> </span><span class="RktSym">sexp</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym">atom?</span><span class="hspace"> </span><span class="RktSym">sexp</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">for-atom</span><span class="hspace"> </span><span class="RktSym">sexp</span><span class="RktPn">)</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._else%29%29" class="RktStxLink" data-pltdoc="x">else</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">for-sl</span><span class="hspace"> </span><span class="RktSym">sexp</span><span class="RktPn">)</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_four.html#%28tech._sl%29" class="techoutside" data-pltdoc="x"><span class="techinside">SL</span></a><span class="RktCmt"> -> </span><a href="part_four.html#%28tech._s._expr%29" class="techoutside" data-pltdoc="x"><span class="techinside">S-expr</span></a><span class="RktCmt"> </span></td></tr><tr><td><span class="hspace">  
|
||
|
line. Furthermore, neither definition is recursive. Hence we can
|
||
|
<span style="font-style: italic">in-line</span> the functions in <span class="RktSym">for-sexp</span>. In-lining means
|
||
|
replacing <span class="RktPn">(</span><span class="RktSym">for-atom</span><span class="stt"> </span><span class="RktSym">sexp</span><span class="RktPn">)</span> with <span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._if%29%29" class="RktStxLink" data-pltdoc="x">if</a></span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._equal~3f%29%29" class="RktValLink" data-pltdoc="x">equal?</a></span><span class="stt"> </span><span class="RktSym">sexp</span><span class="stt"> </span><span class="RktSym">old</span><span class="RktPn">)</span><span class="stt"> </span><span class="RktSym">new</span><span class="stt"> </span><span class="RktSym">sexp</span><span class="RktPn">)</span>, that is, we replace the<span class="refelem"><span class="refcolumn"><span class="refcontent">While <span class="RktSym">sexp</span> is also a
|
||
|
parameter, this substitution is really acceptable because it, too, stands
|
||
|
in for an actual value.</span></span></span> parameter <span class="RktSym">at</span> with the actual argument
|
||
|
<span class="RktSym">sexp</span>. Similarly, for <span class="RktPn">(</span><span class="RktSym">for-sl</span><span class="stt"> </span><span class="RktSym">sexp</span><span class="RktPn">)</span> we put in
|
||
|
<span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._map%29%29" class="RktValLink" data-pltdoc="x">map</a></span><span class="stt"> </span><span class="RktSym">for-sexp</span><span class="stt"> </span><span class="RktSym">sexp</span><span class="RktPn">)</span>; see the bottom half of
|
||
|
<a href="part_four.html#%28counter._%28figure._fig~3asimplifying2%29%29" data-pltdoc="x">figure <span class="FigureRef">121</span></a>. All we are left with now is a function
|
||
|
whose definition introduces one <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._local%29%29" class="RktStxLink" data-pltdoc="x">local</a></span> function, which is called
|
||
|
on the same major argument. If we systematically supplied the other two
|
||
|
arguments, we would immediately see that the locally defined function can
|
||
|
be used in lieu of the outer one.</p><p><div class="SIntrapara">Here is the result of translating this last thought into code: <a name="(idx._(gentag._515))"></a>
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">substitute</span><span class="hspace"> </span><span class="RktSym">sexp</span><span class="hspace"> </span><span class="RktSym">old</span><span class="hspace"> </span><span class="RktSym">new</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym">atom?</span><span class="hspace"> </span><span class="RktSym">sexp</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._if%29%29" class="RktStxLink" data-pltdoc="x">if</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._equal~3f%29%29" class="RktValLink" data-pltdoc="x">equal?</a></span><span class="hspace"> </span><span class="RktSym">sexp</span><span class="hspace"> </span><span class="RktSym">old</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">new</span><span class="hspace"> </span><span class="RktSym">sexp</span><span class="RktPn">)</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._else%29%29" class="RktStxLink" data-pltdoc="x">else</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._map%29%29" class="RktValLink" data-pltdoc="x">map</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._lambda%29%29" class="RktStxLink" data-pltdoc="x">lambda</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">s</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">substitute</span><span class="hspace"> </span><span class="RktSym">s</span><span class="hspace"> </span><span class="RktSym">old</span><span class="hspace"> </span><span class="RktSym">new</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">sexp</span><span class="RktPn">)</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">Stop! Explain why we had to use <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._lambda%29%29" class="RktStxLink" data-pltdoc="x">lambda</a></span> for this last
|
||
|
simplification.</div></p><h3>20<tt> </tt><a name="(part._ch~3afiles)"></a>Iterative Refinement</h3><p>When you develop real-world programs, you may confront complex forms of
|
||
|
information and the problem of representing them with data. The best strategy to
|
||
|
approach this task is to use <a name="(idx._(gentag._516))"></a><span style="font-style: italic">iterative refinement</span>, a well-known scientific
|
||
|
process. A scientist’s problem is to represent a part of the real world, using
|
||
|
some form of mathematics. The result of the effort is called a model. The
|
||
|
scientist then tests the model in many ways, in particular by predicting the
|
||
|
outcome of experiments. If the discrepancies between the predictions and the
|
||
|
measurements are too large, the model is refined with the goal of improving the
|
||
|
predictions. This iterative process continues until the predictions are
|
||
|
sufficiently accurate.</p><p>Consider a physicist who wishes to predict a rocket’s flight path. While a
|
||
|
“rocket as a point” representation is simple, it is also quite
|
||
|
inaccurate, failing to account for air friction, for example. In response,
|
||
|
the physicist may add the rocket’s rough contour and introduce the
|
||
|
necessary mathematics to represent friction. This second model is a
|
||
|
<span style="font-style: italic">refinement</span> of the first model. In general, a scientist
|
||
|
repeats—<wbr></wbr>or as programmers say, <span style="font-style: italic">iterates</span>—<wbr></wbr>this process until
|
||
|
the model predicts the rocket’s flight path with sufficient accuracy.</p><p>A programmer trained in a computer science department should proceed like this
|
||
|
physicist. The key is to find an accurate data representation of the real-world
|
||
|
information and functions that process them appropriately. Complicated situations
|
||
|
call for a refinement process to get to a sufficient data representation combined
|
||
|
with the proper functions. The process starts with the essential pieces of
|
||
|
information and adds others as needed. Sometimes a programmer must refine a model
|
||
|
<span style="font-weight: bold">after</span> the program has been deployed because users request additional
|
||
|
functionality.</p><p>So far we have used iterative refinement for you when it came to complex forms of
|
||
|
data. This chapter illustrates iterative refinement as a principle of program
|
||
|
development with an extended example, representing and processing (portions of) a
|
||
|
computer’s file system. We start with a brief discussion of the file system and
|
||
|
then iteratively develop three data representations. Along the way, we propose
|
||
|
some programming exercises so that you see how the <a name="(idx._(gentag._517))"></a>design recipe also helps
|
||
|
modify existing programs.</p><h4>20.1<tt> </tt><a name="(part._sec~3afiles-what)"></a>Data Analysis</h4><p>Before you turn off DrRacket, you want to make sure that all your work is
|
||
|
safely stashed away somewhere. Otherwise you have to reenter
|
||
|
everything<span class="refelem"><span class="refcolumn"><span class="refcontent">A file is really a sequence of <span style="font-style: italic">bytes</span>,
|
||
|
one after another. Try to define the class of files.</span></span></span> when you fire up
|
||
|
DrRacket next. So you ask your computer to save programs and data in
|
||
|
<span style="font-style: italic">files</span>. A file is roughly a string.</p><blockquote class="Figure"><blockquote class="Centerfigure"><blockquote class="FigureInside"><p><img style="vertical-align: -0.0px; margin: -3px -3px -3px -3px;" src="pict_145.png" alt="image" width="376.759765625" height="308.6875"/></p></blockquote></blockquote><p class="Centertext"><span class="Legend"><span class="FigureTarget"><a name="(counter._(figure._fig~3aaccountant))" x-target-lift="Figure"></a>Figure 123: </span>A sample directory tree</span></p></blockquote><p>On most computer systems, files are organized in <span style="font-style: italic">directories</span> or
|
||
|
<span style="font-style: italic">folders</span>. Roughly speaking, a directory contains some files and
|
||
|
some more directories. The latter are called sub-directories and may
|
||
|
contain yet more sub-directories and files. Because of the hierarchy, we
|
||
|
speak of <span style="font-style: italic">directory trees</span>.</p><p><a href="part_four.html#%28counter._%28figure._fig~3aaccountant%29%29" data-pltdoc="x">Figure <span class="FigureRef">123</span></a> contains a graphical sketch of a small directory tree,
|
||
|
and the picture explains why computer scientists call them trees. Contrary
|
||
|
to convention in computer science, the figure shows the tree growing upward, with a root
|
||
|
directory named <span class="stt">TS</span>. The root directory contains one file, called <span class="stt">read!</span>,
|
||
|
and two sub-directories, called <span class="stt">Text</span> and <span class="stt">Libs</span>, respectively. The first
|
||
|
sub-directory, <span class="stt">Text</span>, contains only three files; the latter, <span class="stt">Libs</span>,
|
||
|
contains only two sub-directories, each of which contains at least one
|
||
|
file. Finally, each box has one of two annotations: a directory is annotated with
|
||
|
<span class="stt">DIR</span>, and a file is annotated with a number, its size.</p><p><a name="(counter._(exercise._ex~3adir0))"></a><span style="font-weight: bold">Exercise</span> 329. How many times does a file name <span class="stt">read!</span> occur in the
|
||
|
directory tree <span class="stt">TS</span>? Can you describe the path from the root directory to the
|
||
|
occurrences? What is the total size of all the files in the tree? What is the
|
||
|
total size of the directory if each directory node has size <span class="RktVal">1</span>? How many
|
||
|
levels of directories does it contain? <a href="part_four.html#%28counter._%28exercise._ex~3adir0%29%29" class="ex-end" data-pltdoc="x"></a></p><h4>20.2<tt> </tt><a name="(part._sec~3afiles-models)"></a>Refining Data Definitions</h4><p><a href="part_four.html#%28counter._%28exercise._ex~3adir0%29%29" data-pltdoc="x">Exercise 329</a> lists some of the questions that users routinely ask about
|
||
|
directories. To answer such questions, the computer’s operating system provides
|
||
|
programs that can answer them. If you want to design such
|
||
|
programs, you need to develop a data representation for directory trees.</p><p>In this section, we use iterative refinement to develop three such data
|
||
|
representations. For each stage, we need to decide which attributes to include
|
||
|
and which to ignore. Consider the directory tree in <a href="part_four.html#%28counter._%28figure._fig~3aaccountant%29%29" data-pltdoc="x">figure <span class="FigureRef">123</span></a>
|
||
|
and imagine how it is created. When a user first creates a directory, it is
|
||
|
empty. As time goes by, the user adds files and directories. In general, a user
|
||
|
refers to files by names but mostly thinks of directories as containers.</p><p><div class="SIntrapara"><span style="font-weight: bold">Model 1</span> Our thought experiment suggests that our first model should focus
|
||
|
on files as atomic entities with a name and directories as containers. Here is a
|
||
|
data definition that deals with directories as lists and files as strings,
|
||
|
that is, their names:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">A </span><a name="(tech._dir..v1)"></a><span style="font-style: italic">Dir.v1</span><span class="RktCmt"> (short for </span><span style="font-style: italic">directory</span><span class="RktCmt">) is one of: </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">–</span><span class="RktCmt"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">–</span><span class="RktCmt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="stt"> </span><a href="part_four.html#%28tech._file..v1%29" class="techoutside" data-pltdoc="x"><span class="techinside">File.v1</span></a><span class="stt"> </span><a href="part_four.html#%28tech._dir..v1%29" class="techoutside" data-pltdoc="x"><span class="techinside">Dir.v1</span></a><span class="RktPn">)</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">–</span><span class="RktCmt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="stt"> </span><a href="part_four.html#%28tech._dir..v1%29" class="techoutside" data-pltdoc="x"><span class="techinside">Dir.v1</span></a><span class="stt"> </span><a href="part_four.html#%28tech._dir..v1%29" class="techoutside" data-pltdoc="x"><span class="techinside">Dir.v1</span></a><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">A </span><a name="(tech._file..v1)"></a><span style="font-style: italic">File.v1</span><span class="RktCmt"> is a </span><a href="part_one.html#%28tech._string%29" class="techoutside" data-pltdoc="x"><span class="techinside">String</span></a><span class="RktCmt">. </span></td></tr></table></blockquote></div><div class="SIntrapara">The names have a <span style="font-style: italic">.v1</span> suffix to distinguish them from future refinements.</div></p><p><a name="(counter._(exercise._ex~3afile-example1))"></a><span style="font-weight: bold">Exercise</span> 330. Translate the directory tree in
|
||
|
<a href="part_four.html#%28counter._%28figure._fig~3aaccountant%29%29" data-pltdoc="x">figure <span class="FigureRef">123</span></a> into a data representation according to model 1. <a href="part_four.html#%28counter._%28exercise._ex~3afile-example1%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._(exercise._ex~3adir-how-many1))"></a><span style="font-weight: bold">Exercise</span> 331. Design the function <span class="RktSym">how-many</span>, which
|
||
|
determines how many files a given <a href="part_four.html#%28tech._dir..v1%29" class="techoutside" data-pltdoc="x"><span class="techinside">Dir.v1</span></a> contains. Remember to follow the
|
||
|
design recipe; <a href="part_four.html#%28counter._%28exercise._ex~3afile-example1%29%29" data-pltdoc="x">exercise 330</a> provides you with data examples. <a href="part_four.html#%28counter._%28exercise._ex~3adir-how-many1%29%29" class="ex-end" data-pltdoc="x"></a></p><p><div class="SIntrapara"><span style="font-weight: bold">Model 2</span> If you solved <a href="part_four.html#%28counter._%28exercise._ex~3adir-how-many1%29%29" data-pltdoc="x">exercise 331</a>, you know that this first
|
||
|
data definition is still reasonably simple. But, it also obscures the nature of
|
||
|
directories. With this first representation, we would not be able to list all the
|
||
|
names of the sub-directories of some given directory. To model directories in a
|
||
|
more faithful manner than containers, we must introduce a structure type that
|
||
|
combines a name with a container:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define-struct%29%29" class="RktStxLink" data-pltdoc="x">define-struct</a></span><span class="hspace"> </span><span class="RktSym">dir</span><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym">name</span><span class="hspace"> </span><span class="RktSym">content</span><span class="RktPn">]</span><span class="RktPn">)</span></p></blockquote></div></p><p><div class="SIntrapara">This new structure type, in turn, suggests the following revision of the data definition:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">A </span><a name="(tech._dir..v2)"></a><span style="font-style: italic">Dir.v2</span><span class="RktCmt"> is a structure: </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">make-dir</span><span class="stt"> </span><a href="part_one.html#%28tech._string%29" class="techoutside" data-pltdoc="x"><span class="techinside">String</span></a><span class="stt"> </span><a href="part_four.html#%28tech._lofd%29" class="techoutside" data-pltdoc="x"><span class="techinside">LOFD</span></a><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">An </span><a name="(tech._lofd)"></a><span style="font-style: italic">LOFD</span><span class="RktCmt"> (short for </span><span style="font-style: italic">list of files and directories</span><span class="RktCmt">) is one of:</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">–</span><span class="RktCmt"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">–</span><span class="RktCmt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="stt"> </span><a href="part_four.html#%28tech._file..v2%29" class="techoutside" data-pltdoc="x"><span class="techinside">File.v2</span></a><span class="stt"> </span><span class="RktSym">LOFD</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">–</span><span class="RktCmt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="stt"> </span><a href="part_four.html#%28tech._dir..v2%29" class="techoutside" data-pltdoc="x"><span class="techinside">Dir.v2</span></a><span class="stt"> </span><a href="part_four.html#%28tech._lofd%29" class="techoutside" data-pltdoc="x"><span class="techinside">LOFD</span></a><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">A </span><a name="(tech._file..v2)"></a><span style="font-style: italic">File.v2</span><span class="RktCmt"> is a </span><a href="part_one.html#%28tech._string%29" class="techoutside" data-pltdoc="x"><span class="techinside">String</span></a><span class="RktCmt">. </span></td></tr></table></blockquote></div><div class="SIntrapara">Note how the data definition for <a href="part_four.html#%28tech._dir..v2%29" class="techoutside" data-pltdoc="x"><span class="techinside">Dir.v2</span></a> refers to the definition for
|
||
|
<a href="part_four.html#%28tech._lofd%29" class="techoutside" data-pltdoc="x"><span class="techinside">LOFD</span></a>s, and the one for <a href="part_four.html#%28tech._lofd%29" class="techoutside" data-pltdoc="x"><span class="techinside">LOFD</span></a>s refers back to that of <a href="part_four.html#%28tech._dir..v2%29" class="techoutside" data-pltdoc="x"><span class="techinside">Dir.v2</span></a>.
|
||
|
The two definitions are mutually recursive.</div></p><p><a name="(counter._(exercise._ex~3afile-example2))"></a><span style="font-weight: bold">Exercise</span> 332. Translate the directory tree in
|
||
|
<a href="part_four.html#%28counter._%28figure._fig~3aaccountant%29%29" data-pltdoc="x">figure <span class="FigureRef">123</span></a> into a data representation according to model 2. <a href="part_four.html#%28counter._%28exercise._ex~3afile-example2%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._(exercise._ex~3adir-how-many2))"></a><span style="font-weight: bold">Exercise</span> 333. Design the function <span class="RktSym">how-many</span>, which
|
||
|
determines how many files a given <a href="part_four.html#%28tech._dir..v2%29" class="techoutside" data-pltdoc="x"><span class="techinside">Dir.v2</span></a> contains.
|
||
|
<a href="part_four.html#%28counter._%28exercise._ex~3afile-example2%29%29" data-pltdoc="x">Exercise 332</a> provides you with data examples. Compare your result
|
||
|
with that of <a href="part_four.html#%28counter._%28exercise._ex~3adir-how-many1%29%29" data-pltdoc="x">exercise 331</a>. <a href="part_four.html#%28counter._%28exercise._ex~3adir-how-many2%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._(exercise._ex~3aalt-dir1))"></a><span style="font-weight: bold">Exercise</span> 334. Show how to equip a directory with two more attributes:
|
||
|
size and readability. The former measures how much space the directory itself (as
|
||
|
opposed to its content) consumes; the latter specifies whether
|
||
|
anyone else besides the user may browse the content of the directory. <a href="part_four.html#%28counter._%28exercise._ex~3aalt-dir1%29%29" class="ex-end" data-pltdoc="x"></a></p><p><div class="SIntrapara"><span style="font-weight: bold">Model 3</span> Like directories, files have attributes. To introduce these, we
|
||
|
proceed just as above. First, we define a structure for files:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define-struct%29%29" class="RktStxLink" data-pltdoc="x">define-struct</a></span><span class="hspace"> </span><span class="RktSym">file</span><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym">name</span><span class="hspace"> </span><span class="RktSym">size</span><span class="hspace"> </span><span class="RktSym">content</span><span class="RktPn">]</span><span class="RktPn">)</span></p></blockquote></div><div class="SIntrapara">Second, we provide a data definition:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">A </span><a name="(tech._file..v3)"></a><span style="font-style: italic">File.v3</span><span class="RktCmt"> is a structure: </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">make-file</span><span class="stt"> </span><a href="part_one.html#%28tech._string%29" class="techoutside" data-pltdoc="x"><span class="techinside">String</span></a><span class="stt"> </span><a href="part_two.html#%28tech._n%29" class="techoutside" data-pltdoc="x"><span class="techinside">N</span></a><span class="stt"> </span><a href="part_one.html#%28tech._string%29" class="techoutside" data-pltdoc="x"><span class="techinside">String</span></a><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">As indicated by the field names, the string represents the name of the file, the
|
||
|
natural number its size, and the string its content.</div></p><p><div class="SIntrapara">Finally, let’s split the <span class="RktSym">content</span> field of directories into two pieces: a
|
||
|
list of files and a list of sub-directories. This change requires a revision of
|
||
|
the structure type definition:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define-struct%29%29" class="RktStxLink" data-pltdoc="x">define-struct</a></span><span class="hspace"> </span><span class="RktSym">dir.v3</span><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym">name</span><span class="hspace"> </span><span class="RktSym">dirs</span><span class="hspace"> </span><span class="RktSym">files</span><span class="RktPn">]</span><span class="RktPn">)</span></p></blockquote></div><div class="SIntrapara">Here is the refined data definition:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">A </span><a name="(tech._dir..v3)"></a><span style="font-style: italic">Dir.v3</span><span class="RktCmt"> is a structure: </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">make-dir.v3</span><span class="stt"> </span><a href="part_one.html#%28tech._string%29" class="techoutside" data-pltdoc="x"><span class="techinside">String</span></a><span class="stt"> </span><a href="part_four.html#%28tech._dir%2A%29" class="techoutside" data-pltdoc="x"><span class="techinside">Dir*</span></a><span class="stt"> </span><a href="part_four.html#%28tech._file%2A%29" class="techoutside" data-pltdoc="x"><span class="techinside">File*</span></a><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">A </span><a name="(tech._dir*)"></a><span style="font-style: italic">Dir*</span><span class="RktCmt"> is one of: </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">–</span><span class="RktCmt"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">–</span><span class="RktCmt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="stt"> </span><a href="part_four.html#%28tech._dir..v3%29" class="techoutside" data-pltdoc="x"><span class="techinside">Dir.v3</span></a><span class="stt"> </span><a href="part_four.html#%28tech._dir%2A%29" class="techoutside" data-pltdoc="x"><span class="techinside">Dir*</span></a><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">A </span><a name="(tech._file*)"></a><span style="font-style: italic">File*</span><span class="RktCmt"> is one of: </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">–</span><span class="RktCmt"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">–</span><span class="RktCmt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="stt"> </span><a href="part_four.html#%28tech._file..v3%29" class="techoutside" data-pltdoc="x"><span class="techinside">File.v3</span></a><span class="stt"> </span><a href="part_four.html#%28tech._file%2A%29" class="techoutside" data-pltdoc="x"><span class="techinside">File*</span></a><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">Following a convention in computer science, the use of <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._%2A%29%29" class="RktValLink" data-pltdoc="x">*</a></span> as the ending
|
||
|
of a name suggests “many” and is a marker distinguishing the name from similar
|
||
|
ones: <a href="part_four.html#%28tech._file..v3%29" class="techoutside" data-pltdoc="x"><span class="techinside">File.v3</span></a> and <a href="part_four.html#%28tech._dir..v3%29" class="techoutside" data-pltdoc="x"><span class="techinside">Dir.v3</span></a>.</div></p><p><a name="(counter._(exercise._ex~3afile-example3))"></a><span style="font-weight: bold">Exercise</span> 335. Translate the directory tree in
|
||
|
<a href="part_four.html#%28counter._%28figure._fig~3aaccountant%29%29" data-pltdoc="x">figure <span class="FigureRef">123</span></a> into a data representation according to model 3. Use
|
||
|
<span class="RktVal">""</span> for the content of files. <a href="part_four.html#%28counter._%28exercise._ex~3afile-example3%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._(exercise._ex~3adir-how-many3))"></a><span style="font-weight: bold">Exercise</span> 336. Design the function <span class="RktSym">how-many</span>, which
|
||
|
determines how many files a given <a href="part_four.html#%28tech._dir..v3%29" class="techoutside" data-pltdoc="x"><span class="techinside">Dir.v3</span></a> contains.
|
||
|
<a href="part_four.html#%28counter._%28exercise._ex~3afile-example3%29%29" data-pltdoc="x">Exercise 335</a> provides you with data examples. Compare your result
|
||
|
with that of <a href="part_four.html#%28counter._%28exercise._ex~3adir-how-many2%29%29" data-pltdoc="x">exercise 333</a>.</p><p>Given the complexity of the data definition, contemplate how anyone can
|
||
|
design correct functions. Why are you confident that <span class="RktSym">how-many</span>
|
||
|
produces correct results? <a href="part_four.html#%28counter._%28exercise._ex~3adir-how-many3%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._(exercise._ex~3adir-how-many-map))"></a><span style="font-weight: bold">Exercise</span> 337. Use <a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a> to simplify the data
|
||
|
definition <a href="part_four.html#%28tech._dir..v3%29" class="techoutside" data-pltdoc="x"><span class="techinside">Dir.v3</span></a>. Then use ISL+’s list-processing functions
|
||
|
from <a href="part_three.html#%28counter._%28figure._fig~3aisl-ho-list%29%29" data-pltdoc="x">figures <span class="FigureRef">95</span></a> and <a href="part_three.html#%28counter._%28figure._fig~3aisl-ho-list2%29%29" data-pltdoc="x"><span class="FigureRef">96</span></a> to simplify the
|
||
|
function definition(s) for the solution of <a href="part_four.html#%28counter._%28exercise._ex~3adir-how-many3%29%29" data-pltdoc="x">exercise 336</a>. <a href="part_four.html#%28counter._%28exercise._ex~3adir-how-many-map%29%29" class="ex-end" data-pltdoc="x"></a></p><p>Starting with a simple representation of the first model and refining it
|
||
|
step-by-step, we have developed a reasonably accurate data representation
|
||
|
for directory
|
||
|
trees. Indeed, this third data representation captures the nature of a directory
|
||
|
tree much more faithfully than the first two. Based on this model, we can create
|
||
|
a number of other functions that users expect from a computer’s operating system.</p><h4>20.3<tt> </tt><a name="(part._sec~3arefine-funcs)"></a>Refining Functions</h4><p><div class="SIntrapara">To make the following exercises somewhat realistic, DrRacket comes
|
||
|
with<span class="refelem"><span class="refcolumn"><span class="refcontent">Add <span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._require%29%29" class="RktStxLink" data-pltdoc="x">require</a></span><span class="stt"> </span><span class="RktSym">htdp/dir</span><span class="RktPn">)</span> to the definitions area.</span></span></span> <span class="sroman">the <span class="Smaller"><span style="font-style: italic">dir.rkt</span></span> teachpack</span> from the first
|
||
|
edition of this book. This teachpack introduces the two structure type
|
||
|
definitions from model 3, though without the <span style="font-style: italic">.v3</span>
|
||
|
suffix. Furthermore, the teachpack provides a function that creates
|
||
|
representations of directory trees on your computer:<a name="(idx._(gentag._518))"></a>
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_one.html#%28tech._string%29" class="techoutside" data-pltdoc="x"><span class="techinside">String</span></a><span class="RktCmt"> -> </span><a href="part_four.html#%28tech._dir..v3%29" class="techoutside" data-pltdoc="x"><span class="techinside">Dir.v3</span></a></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">creates a representation of the </span><span class="stt">a-path</span><span class="RktCmt"> directory </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">create-dir</span><span class="hspace"> </span><span class="RktSym">a-path</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">For example, if you open DrRacket and enter the following three lines into the
|
||
|
definitions area:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">O</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">create-dir</span><span class="hspace"> </span><span class="RktVal">"/Users/..."</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">on OS X </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">L</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">create-dir</span><span class="hspace"> </span><span class="RktVal">"/var/log/"</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">on Linux</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">W</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">create-dir</span><span class="hspace"> </span><span class="RktVal">"C:\\Users\\..."</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">on Windows </span></td></tr></table></blockquote></div><div class="SIntrapara">you get data representations of directories on your computer after you
|
||
|
<span style="font-weight: bold">save</span> and then run the program. Indeed, you could use
|
||
|
<span class="RktSym">create-dir</span> to map the entire file system on your computer to an
|
||
|
instance of <a href="part_four.html#%28tech._dir..v3%29" class="techoutside" data-pltdoc="x"><span class="techinside">Dir.v3</span></a>.</div></p><p><span style="font-weight: bold">Warnings</span> (1) For large directory trees, DrRacket may need a lot of time
|
||
|
to build a representation. Use <span class="RktSym">create-dir</span> on small directory
|
||
|
trees first. (2) Do <span style="font-weight: bold">not</span> define your own <span style="font-style: italic">dir</span> structure
|
||
|
type. The teachpack already defines them, and you must not define a
|
||
|
structure type twice.</p><p>Although <span class="RktSym">create-dir</span> delivers only a representation of a directory tree,
|
||
|
it is sufficiently realistic to give you a sense of what it is like to design
|
||
|
programs at that level. The following exercises illustrate this point. They use
|
||
|
<span style="font-style: italic">Dir</span> to refer to the generic idea of a data representation for directory
|
||
|
trees. Use the simplest data definition of <span style="font-style: italic">Dir</span> that allows you to complete
|
||
|
the respective exercise. Feel free to use the data definition from
|
||
|
<a href="part_four.html#%28counter._%28exercise._ex~3adir-how-many-map%29%29" data-pltdoc="x">exercise 337</a> and the functions from
|
||
|
<a href="part_three.html#%28counter._%28figure._fig~3aisl-ho-list%29%29" data-pltdoc="x">figures <span class="FigureRef">95</span></a> and <a href="part_three.html#%28counter._%28figure._fig~3aisl-ho-list2%29%29" data-pltdoc="x"><span class="FigureRef">96</span></a>.</p><p><a name="(counter._(exercise._ex~3adir-how-many4))"></a><span style="font-weight: bold">Exercise</span> 338. Use <span class="RktSym">create-dir</span> to turn some of your
|
||
|
directories into ISL+ data representations. Then use <span class="RktSym">how-many</span>
|
||
|
from <a href="part_four.html#%28counter._%28exercise._ex~3adir-how-many3%29%29" data-pltdoc="x">exercise 336</a> to count how many files they contain. Why
|
||
|
are you confident that <span class="RktSym">how-many</span> produces correct results for
|
||
|
these directories? <a href="part_four.html#%28counter._%28exercise._ex~3adir-how-many4%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._(exercise._ex~3afile-find))"></a><span style="font-weight: bold">Exercise</span> 339. Design <span class="RktSym">find?</span>. The function consumes a
|
||
|
<span style="font-style: italic">Dir</span> and a file name and determines whether or not a file with this name
|
||
|
occurs in the directory tree. <a href="part_four.html#%28counter._%28exercise._ex~3afile-find%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._(exercise._ex~3afile-ls))"></a><span style="font-weight: bold">Exercise</span> 340. Design the function <span class="RktSym">ls</span>, which lists the names of
|
||
|
all files and directories in a given <span style="font-style: italic">Dir</span>. <a href="part_four.html#%28counter._%28exercise._ex~3afile-ls%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._(exercise._ex~3afile-du))"></a><span style="font-weight: bold">Exercise</span> 341. Design <span class="RktSym">du</span>, a function that consumes a
|
||
|
<span style="font-style: italic">Dir</span> and computes the total size of all the files in the entire directory
|
||
|
tree. Assume that storing a directory in a <span style="font-style: italic">Dir</span> structure costs <span class="RktVal">1</span>
|
||
|
file storage unit. In the real world, a directory is basically a special file, and
|
||
|
its size depends on how large its associated directory is. <a href="part_four.html#%28counter._%28exercise._ex~3afile-du%29%29" class="ex-end" data-pltdoc="x"></a></p><p><div class="SIntrapara">The remaining exercises rely on the notion of a path, which for our purposes is a
|
||
|
list of names:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">A </span><a name="(tech._path)"></a><span style="font-style: italic">Path</span><span class="RktCmt"> is [</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> </span><a href="part_one.html#%28tech._string%29" class="techoutside" data-pltdoc="x"><span class="techinside">String</span></a><span class="RktCmt">].</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span style="font-weight: bold">interpretation</span><span class="RktCmt"> directions into a directory tree</span></td></tr></table></blockquote></div><div class="SIntrapara">Take a second look at <a href="part_four.html#%28counter._%28figure._fig~3aaccountant%29%29" data-pltdoc="x">figure <span class="FigureRef">123</span></a>. In that diagram, the path from
|
||
|
<span class="stt">TS</span> to <span class="stt">part1</span> is <span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="stt"> </span><span class="RktVal">"TS"</span><span class="stt"> </span><span class="RktVal">"Text"</span><span class="stt"> </span><span class="RktVal">"part1"</span><span class="RktPn">)</span>. Similarly,
|
||
|
the path from <span class="stt">TS</span> to <span class="stt">Code</span> is <span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="stt"> </span><span class="RktVal">"TS"</span><span class="stt"> </span><span class="RktVal">"Libs"</span><span class="stt"> </span><span class="RktVal">"Code"</span><span class="RktPn">)</span>.</div></p><p><a name="(counter._(exercise._ex~3afile-find-path))"></a><span style="font-weight: bold">Exercise</span> 342. Design <span class="RktSym">find</span>. The function consumes a
|
||
|
directory <span class="RktSym">d</span> and a file name <span class="RktSym">f</span>. If <span class="RktPn">(</span><span class="RktSym">find?</span><span class="stt"> </span><span class="RktSym">d</span><span class="stt"> </span><span class="RktSym">f</span><span class="RktPn">)</span> is <span class="RktVal">#true</span>,
|
||
|
<span class="RktSym">find</span> produces a path to a file with name <span class="RktSym">f</span>; otherwise it
|
||
|
produces <span class="RktVal">#false</span>.</p><p><span style="font-weight: bold">Hint</span> While it is tempting to first check whether the file name occurs in the
|
||
|
directory tree, you have to do so for every single sub-directory. Hence it is
|
||
|
better to combine the functionality of <span class="RktSym">find?</span> and <span class="RktSym">find</span>.</p><p><span style="font-weight: bold">Challenge</span> The <span class="RktSym">find</span> function discovers only one of the two files named
|
||
|
<span class="stt">read!</span> in <a href="part_four.html#%28counter._%28figure._fig~3aaccountant%29%29" data-pltdoc="x">figure <span class="FigureRef">123</span></a>. Design <span class="RktSym">find-all</span>, which
|
||
|
generalizes <span class="RktSym">find</span> and produces the list of all paths that lead to
|
||
|
<span class="RktSym">f</span> in <span class="RktSym">d</span>. What should <span class="RktSym">find-all</span> produce when
|
||
|
<span class="RktPn">(</span><span class="RktSym">find?</span><span class="stt"> </span><span class="RktSym">d</span><span class="stt"> </span><span class="RktSym">f</span><span class="RktPn">)</span> is <span class="RktVal">#false</span>? Is this part of the problem really a
|
||
|
challenge compared to the basic problem? <a href="part_four.html#%28counter._%28exercise._ex~3afile-find-path%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._(exercise._ex~3afile-ls-.R))"></a><span style="font-weight: bold">Exercise</span> 343. Design the function <span class="RktSym">ls-R</span>, which lists the paths
|
||
|
to <span style="font-weight: bold">all</span> files contained in a given <span style="font-style: italic">Dir</span>. <a href="part_four.html#%28counter._%28exercise._ex~3afile-ls-.R%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._(exercise._ex~3afile-find-path-compose))"></a><span style="font-weight: bold">Exercise</span> 344. Redesign <span class="RktSym">find-all</span> from
|
||
|
<a href="part_four.html#%28counter._%28exercise._ex~3afile-find-path%29%29" data-pltdoc="x">exercise 342</a> using <span class="RktSym">ls-R</span> from <a href="part_four.html#%28counter._%28exercise._ex~3afile-ls-.R%29%29" data-pltdoc="x">exercise 343</a>. This is
|
||
|
design by composition, and if you solved the challenge part of
|
||
|
<a href="part_four.html#%28counter._%28exercise._ex~3afile-find-path%29%29" data-pltdoc="x">exercise 342</a> your new function can find directories, too. <a href="part_four.html#%28counter._%28exercise._ex~3afile-find-path-compose%29%29" class="ex-end" data-pltdoc="x"></a></p><h3>21<tt> </tt><a name="(part._ch~3aevaluator)"></a>Refining Interpreters</h3><p>DrRacket is a program. It is a complex one, dealing with many different
|
||
|
kinds of data. Like most complex programs, DrRacket also consists of many
|
||
|
functions: one that allows programmers to edit text, another one that acts
|
||
|
like the interactions area, a third one that checks whether definitions and
|
||
|
expressions are “grammatical,” and so on.</p><p>In this chapter, we show you how to design the function that implements the
|
||
|
heart of the interactions area. Naturally, we use <a name="(idx._(gentag._519))"></a>iterative refinement for
|
||
|
this design project. As a matter of fact, the very idea of focusing on
|
||
|
this aspect of DrRacket is another instance of refinement, namely, the
|
||
|
obvious one of implementing only one piece of functionality.</p><p>Simply put, the interactions area performs the task of determining the
|
||
|
values of expressions that you enter. After you click <span class="emph">RUN</span>, the
|
||
|
interactions area knows about all the definitions. It is then ready to
|
||
|
accept an expression that may refer to these definitions, to determine the
|
||
|
value of this expression, and to repeat this cycle as often as you
|
||
|
wish. For this reason, many people also refer to the interactions area as
|
||
|
the <span style="font-style: italic">read-eval-print</span> loop, where <span style="font-style: italic">eval</span> is short for
|
||
|
<span style="font-style: italic">evaluator</span>, a function that is also called <span style="font-style: italic">interpreter</span>.</p><p>Like this book, our refinement process starts with numeric BSL
|
||
|
expressions. They are simple; they do not assume an understanding of
|
||
|
definitions; and even your sister in fifth grade can determine their
|
||
|
value. Once you understand this first step, you know the difference
|
||
|
between a BSL expression and its representation. Next we move on to
|
||
|
expressions with variables. The last step is to add definitions.</p><h4>21.1<tt> </tt><a name="(part._sec~3ainterpreter)"></a>Interpreting Expressions</h4><p>Our first task is to agree on a data representation for BSL programs.
|
||
|
That is, we must figure out how to represent a BSL expression as a
|
||
|
piece of BSL data. At first, this sounds strange and unusual, but it is
|
||
|
not difficult. Suppose we just want to represent numbers, additions, and
|
||
|
multiplications for a start. Clearly, numbers can stand for numbers. An
|
||
|
addition expression, however, calls for compound data because it contains
|
||
|
two expressions and because it is distinct from a multiplication
|
||
|
expression, which also needs a data representation.</p><p><div class="SIntrapara">Following <a href="part_one.html#%28part._ch~3astructure%29" data-pltdoc="x">Adding Structure</a>, a straightforward way to
|
||
|
represent additions and multiplications is to define two structure types,
|
||
|
each with two fields:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define-struct%29%29" class="RktStxLink" data-pltdoc="x">define-struct</a></span><span class="hspace"> </span><span class="RktSym">add</span><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym"><a href="https://docs.racket-lang.org/teachpack/2htdpuniverse.html#%28form._world._%28%28lib._2htdp%2Funiverse..rkt%29._left%29%29" class="RktStxLink" data-pltdoc="x">left</a></span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/teachpack/2htdpuniverse.html#%28form._world._%28%28lib._2htdp%2Funiverse..rkt%29._right%29%29" class="RktStxLink" data-pltdoc="x">right</a></span><span class="RktPn">]</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define-struct%29%29" class="RktStxLink" data-pltdoc="x">define-struct</a></span><span class="hspace"> </span><span class="RktSym">mul</span><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym"><a href="https://docs.racket-lang.org/teachpack/2htdpuniverse.html#%28form._world._%28%28lib._2htdp%2Funiverse..rkt%29._left%29%29" class="RktStxLink" data-pltdoc="x">left</a></span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/teachpack/2htdpuniverse.html#%28form._world._%28%28lib._2htdp%2Funiverse..rkt%29._right%29%29" class="RktStxLink" data-pltdoc="x">right</a></span><span class="RktPn">]</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">The intention is that the <span class="RktSym"><a href="https://docs.racket-lang.org/teachpack/2htdpuniverse.html#%28form._world._%28%28lib._2htdp%2Funiverse..rkt%29._left%29%29" class="RktStxLink" data-pltdoc="x">left</a></span> field contains one operand—<wbr></wbr>the
|
||
|
one to the “left” of the operator—<wbr></wbr>and the <span class="RktSym"><a href="https://docs.racket-lang.org/teachpack/2htdpuniverse.html#%28form._world._%28%28lib._2htdp%2Funiverse..rkt%29._right%29%29" class="RktStxLink" data-pltdoc="x">right</a></span> field
|
||
|
contains the other operand. The following table shows three examples:</div></p><blockquote><table cellspacing="0" cellpadding="0" style="border-collapse: collapse;"><tr><td align="left" style="border-bottom: 1px solid black;"><p><span style="font-weight: bold">BSL expression</span></p></td><td align="left" style="border-bottom: 1px solid black;"><p><span class="hspace"> </span></p></td><td align="left" style="border-bottom: 1px solid black;"><p><span style="font-weight: bold">representation of BSL expression</span></p></td></tr><tr><td align="left"><span class="RktVal">3</span></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><span class="RktVal">3</span></td></tr><tr><td align="left"><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._%2B%29%29" class="RktValLink" data-pltdoc="x">+</a></span><span class="hspace"> </span><span class="RktVal">1</span><span class="hspace"> </span><span class="RktVal">1</span><span class="RktPn">)</span></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><span class="RktPn">(</span><span class="RktSym">make-add</span><span class="hspace"> </span><span class="RktVal">1</span><span class="hspace"> </span><span class="RktVal">1</span><span class="RktPn">)</span></td></tr><tr><td align="left"><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._%2A%29%29" class="RktValLink" data-pltdoc="x">*</a></span><span class="hspace"> </span><span class="RktVal">300001</span><span class="hspace"> </span><span class="RktVal">100000</span><span class="RktPn">)</span></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><span class="RktPn">(</span><span class="RktSym">make-mul</span><span class="hspace"> </span><span class="RktVal">300001</span><span class="hspace"> </span><span class="RktVal">100000</span><span class="RktPn">)</span></td></tr></table></blockquote><p><div class="SIntrapara">The next question concerns an expression with sub-expressions:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._%2B%29%29" class="RktValLink" data-pltdoc="x">+</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._%2A%29%29" class="RktValLink" data-pltdoc="x">*</a></span><span class="hspace"> </span><span class="RktVal">3</span><span class="hspace"> </span><span class="RktVal">3</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._%2A%29%29" class="RktValLink" data-pltdoc="x">*</a></span><span class="hspace"> </span><span class="RktVal">4</span><span class="hspace"> </span><span class="RktVal">4</span><span class="RktPn">)</span><span class="RktPn">)</span></p></blockquote></div><div class="SIntrapara">The surprisingly simple answer is that fields may contain any value. In
|
||
|
this particular case, <span class="RktSym"><a href="https://docs.racket-lang.org/teachpack/2htdpuniverse.html#%28form._world._%28%28lib._2htdp%2Funiverse..rkt%29._left%29%29" class="RktStxLink" data-pltdoc="x">left</a></span> and <span class="RktSym"><a href="https://docs.racket-lang.org/teachpack/2htdpuniverse.html#%28form._world._%28%28lib._2htdp%2Funiverse..rkt%29._right%29%29" class="RktStxLink" data-pltdoc="x">right</a></span> may contain
|
||
|
representations of expressions, and you may nest this as deeply as you
|
||
|
wish. See <a href="part_four.html#%28counter._%28figure._fig~3arepresenting-bsl%29%29" data-pltdoc="x">figure <span class="FigureRef">124</span></a> for additional examples.</div></p><blockquote class="Herefigure"><blockquote class="Centerfigure"><blockquote class="FigureInside"><table cellspacing="0" cellpadding="0" style="border-collapse: collapse;"><tr><td align="left" style="border-bottom: 1px solid black;"><p><span style="font-weight: bold">BSL expression</span></p></td><td align="left" style="border-bottom: 1px solid black;"><p><span class="hspace"> </span></p></td><td align="left" style="border-bottom: 1px solid black;"><p><span style="font-weight: bold">representation of BSL expression</span></p></td></tr><tr><td align="left" valign="top"><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._%2B%29%29" class="RktValLink" data-pltdoc="x">+</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._%2A%29%29" class="RktValLink" data-pltdoc="x">*</a></span><span class="hspace"> </span><span class="RktVal">1</span><span class="hspace"> </span><span class="RktVal">1</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">10</span><span class="RktPn">)</span></td><td align="left" valign="top"><p><span class="hspace"> </span></p></td><td align="left" valign="top"><span class="RktPn">(</span><span class="RktSym">make-add</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">make-mul</span><span class="hspace"> </span><span class="RktVal">1</span><span class="hspace"> </span><span class="RktVal">1</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">10</span><span class="RktPn">)</span></td></tr><tr><td align="left" valign="top"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._%2B%29%29" class="RktValLink" data-pltdoc="x">+</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._%2A%29%29" class="RktValLink" data-pltdoc="x">*</a></span><span class="hspace"> </span><span class="RktVal">3</span><span class="hspace"> </span><span class="RktVal">3</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._%2A%29%29" class="RktValLink" data-pltdoc="x">*</a></span><span class="hspace"> </span><span class="RktVal">4</span><span class="hspace"> </span><span class="RktVal">4</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></td><td align="left" valign="top"><p><span class="hspace"> </span></p></td><td align="left" valign="top"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym">make-add</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">make-mul</span><span class="hspace"> </span><span class="RktVal">3</span><span class="hspace"> </span><span class="RktVal">3</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span cla
|
||
|
representation of BSL expressions based on the structure type
|
||
|
definitions of <span class="RktSym">add</span> and <span class="RktSym">mul</span>. Let’s use
|
||
|
<a name="(tech._bsl._expr)"></a><span style="font-style: italic">BSL-expr</span> in analogy for <a href="part_four.html#%28tech._s._expr%29" class="techoutside" data-pltdoc="x"><span class="techinside">S-expr</span></a> for the new class of
|
||
|
data.</p><p><div class="SIntrapara">Translate the following expressions into data:
|
||
|
</div><div class="SIntrapara"><ol><li><p><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._%2B%29%29" class="RktValLink" data-pltdoc="x">+</a></span><span class="stt"> </span><span class="RktVal">10</span><span class="stt"> </span><span class="RktVal"><span class="nobreak">-1</span>0</span><span class="RktPn">)</span></p></li><li><p><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._%2B%29%29" class="RktValLink" data-pltdoc="x">+</a></span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._%2A%29%29" class="RktValLink" data-pltdoc="x">*</a></span><span class="stt"> </span><span class="RktVal">20</span><span class="stt"> </span><span class="RktVal">3</span><span class="RktPn">)</span><span class="stt"> </span><span class="RktVal">33</span><span class="RktPn">)</span></p></li><li><p><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._%2B%29%29" class="RktValLink" data-pltdoc="x">+</a></span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._%2A%29%29" class="RktValLink" data-pltdoc="x">*</a></span><span class="stt"> </span><span class="RktVal">3.14</span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._%2A%29%29" class="RktValLink" data-pltdoc="x">*</a></span><span class="stt"> </span><span class="RktVal">2</span><span class="stt"> </span><span class="RktVal">3</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._%2A%29%29" class="RktValLink" data-pltdoc="x">*</a></span><span class="stt"> </span><span class="RktVal">3.14</span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._%2A%29%29" class="RktValLink" data-pltdoc="x">*</a></span><span class="stt"> </span><span class="RktVal"><span class="nobreak">-1</span></span><span class="stt"> </span><span class="RktVal"><span class="nobreak">-9</span></span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></p></li></ol></div></p><p><div class="SIntrapara">Interpret the following data as expressions:
|
||
|
</div><div class="SIntrapara"><ol><li><p><span class="RktPn">(</span><span class="RktSym">make-add</span><span class="stt"> </span><span class="RktVal"><span class="nobreak">-1</span></span><span class="stt"> </span><span class="RktVal">2</span><span class="RktPn">)</span></p></li><li><p><span class="RktPn">(</span><span class="RktSym">make-add</span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym">make-mul</span><span class="stt"> </span><span class="RktVal"><span class="nobreak">-2</span></span><span class="stt"> </span><span class="RktVal"><span class="nobreak">-3</span></span><span class="RktPn">)</span><span class="stt"> </span><span class="RktVal">33</span><span class="RktPn">)</span>
|
||
|
<span class="refelem"><span class="refcolumn"><span class="refcontent">Here “interpret” means “translate
|
||
|
from data into information.” In contrast, “interpreter” in the
|
||
|
title of this chapter refers to a program that consumes the representation
|
||
|
of a program and produces its value. While the two ideas are related, they
|
||
|
are not the same.</span></span></span></p></li><li><p><span class="RktPn">(</span><span class="RktSym">make-mul</span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym">make-add</span><span class="stt"> </span><span class="RktVal">1</span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym">make-mul</span><span class="stt"> </span><span class="RktVal">2</span><span class="stt"> </span><span class="RktVal">3</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="stt"> </span><span class="RktVal">3.14</span><span class="RktPn">)</span> <a href="part_four.html#%28counter._%28exercise._ex~3absl-dd%29%29" class="ex-end" data-pltdoc="x"></a></p></li></ol></div></p><p>Now that you have a data representation for BSL programs, it is time to
|
||
|
design an evaluator. This function consumes a representation of a BSL
|
||
|
expression and produces its value. Again, this function is unlike any you
|
||
|
have ever designed so it pays off to experiment with some examples. To
|
||
|
this end, either you can use the rules of arithmetic to figure out what
|
||
|
the value of an expression is or you can “play” in the interactions
|
||
|
area of DrRacket. Take a look at the following table for our examples:</p><blockquote><table cellspacing="0" cellpadding="0" style="border-collapse: collapse;"><tr><td align="left" style="border-bottom: 1px solid black;"><p><span style="font-weight: bold">BSL expression</span></p></td><td align="left" style="border-bottom: 1px solid black;"><p><span class="hspace"> </span></p></td><td align="left" style="border-bottom: 1px solid black;"><p><span style="font-weight: bold">its representation</span></p></td><td align="left" style="border-bottom: 1px solid black;"><p><span class="hspace"> </span></p></td><td align="right" style="border-bottom: 1px solid black;"><p><span style="font-weight: bold">its value</span></p></td></tr><tr><td align="left"><span class="RktVal">3</span></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><span class="RktVal">3</span></td><td align="left"><p><span class="hspace"> </span></p></td><td align="right"><span class="RktVal">3</span></td></tr><tr><td align="left"><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._%2B%29%29" class="RktValLink" data-pltdoc="x">+</a></span><span class="hspace"> </span><span class="RktVal">1</span><span class="hspace"> </span><span class="RktVal">1</span><span class="RktPn">)</span></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><span class="RktPn">(</span><span class="RktSym">make-add</span><span class="hspace"> </span><span class="RktVal">1</span><span class="hspace"> </span><span class="RktVal">1</span><span class="RktPn">)</span></td><td align="left"><p><span class="hspace"> </span></p></td><td align="right"><span class="RktVal">2</span></td></tr><tr><td align="left"><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._%2A%29%29" class="RktValLink" data-pltdoc="x">*</a></span><span class="hspace"> </span><span class="RktVal">3</span><span class="hspace"> </span><span class="RktVal">10</span><span class="RktPn">)</span></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><span class="RktPn">(</span><span class="RktSym">make-mul</span><span class="hspace"> </span><span class="RktVal">3</span><span class="hspace"> </span><span class="RktVal">10</span><span class="RktPn">)</span></td><td align="left"><p><span class="hspace"> </span></p></td><td align="right"><span class="RktVal">30</span></td></tr><tr><td align="left"><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._%2B%29%29" class="RktValLink" data-pltdoc="x">+</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._%2A%29%29" class="RktValLink" data-pltdoc="x">*</a></span><span class="hspace"> </span><span class="RktVal">1</span><span class="hspace"> </span><span class="RktVal">1</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">10</span><span class="RktPn">)</span></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><span class="RktPn">(</span><span class="RktSym">make-add</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">make-mul</span><span class="hspace"> </span><span class="RktVal">1</span><span class="hspace"> </span><span class="RktVal">1</span><span class="RktP
|
||
|
values to which a representation of a BSL expression can evaluate. <a href="part_four.html#%28counter._%28exercise._ex~3absl-value%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._(exercise._ex~3absl-eval))"></a><span style="font-weight: bold">Exercise</span> 347. Design <span class="RktSym">eval-expression</span>. The function
|
||
|
consumes a representation of a BSL expression and computes its value. <a href="part_four.html#%28counter._%28exercise._ex~3absl-eval%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._(exercise._ex~3absl-eval-bool))"></a><span style="font-weight: bold">Exercise</span> 348. Develop a data representation for <a href="part_one.html#%28tech._boolean%29" class="techoutside" data-pltdoc="x"><span class="techinside">Boolean</span></a>
|
||
|
BSL expressions constructed from <span class="RktVal">#true</span>, <span class="RktVal">#false</span>,
|
||
|
<span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._and%29%29" class="RktStxLink" data-pltdoc="x">and</a></span>, <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._or%29%29" class="RktStxLink" data-pltdoc="x">or</a></span>, and <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._not%29%29" class="RktValLink" data-pltdoc="x">not</a></span>. Then design
|
||
|
<span class="RktSym">eval-bool-expression</span>, which consumes (representations of)
|
||
|
<a href="part_one.html#%28tech._boolean%29" class="techoutside" data-pltdoc="x"><span class="techinside">Boolean</span></a> BSL expressions and computes their values. What kind of
|
||
|
values do these <a href="part_one.html#%28tech._boolean%29" class="techoutside" data-pltdoc="x"><span class="techinside">Boolean</span></a> expressions yield? <a href="part_four.html#%28counter._%28exercise._ex~3absl-eval-bool%29%29" class="ex-end" data-pltdoc="x"></a></p><p><div class="SIntrapara"><span style="font-weight: bold">Convenience and parsing</span> S-expressions offer a convenient way to
|
||
|
represent BSL expressions in our programming language:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._%2B%29%29" class="RktValLink" data-pltdoc="x">+</a></span><span class="hspace"> </span><span class="RktVal">1</span><span class="hspace"> </span><span class="RktVal">1</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktRes">2</span></p></td></tr><tr><td><span class="stt">> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">+</span><span class="hspace"> </span><span class="RktVal">1</span><span class="hspace"> </span><span class="RktVal">1</span><span class="RktVal">)</span></td></tr><tr><td><p><span class="RktRes">(list '+ 1 1)</span></p></td></tr><tr><td><span class="stt">> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._%2B%29%29" class="RktValLink" data-pltdoc="x">+</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._%2A%29%29" class="RktValLink" data-pltdoc="x">*</a></span><span class="hspace"> </span><span class="RktVal">3</span><span class="hspace"> </span><span class="RktVal">3</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._%2A%29%29" class="RktValLink" data-pltdoc="x">*</a></span><span class="hspace"> </span><span class="RktVal">4</span><span class="hspace"> </span><span class="RktVal">4</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktRes">25</span></p></td></tr><tr><td><span class="stt">> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">+</span><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">*</span><span class="hspace"> </span><span class="RktVal">3</span><span class="hspace"> </span><span class="RktVal">3</span><span class="RktVal">)</span><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">*</span><span class="hspace"> </span><span class="RktVal">4</span><span class="hspace"> </span><span class="RktVal">4</span><span class="RktVal">)</span><span class="RktVal">)</span></td></tr><tr><td><p><span class="RktRes">(list '+ (list '* 3 3) (list '* 4 4))</span></p></td></tr></table></blockquote></div><div class="SIntrapara">By simply putting a quote in front of an expression, we get ISL+ data.</div></p><p>Interpreting an S-expression representation is clumsy, mostly because not
|
||
|
all S-expressions represent <a href="part_four.html#%28tech._bsl._expr%29" class="techoutside" data-pltdoc="x"><span class="techinside">BSL-expr</span></a>s. For example, <span class="RktVal">#true</span>,
|
||
|
<span class="RktVal">"hello"</span>, and <span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">+</span><span class="stt"> </span><span class="RktVal">x</span><span class="stt"> </span><span class="RktVal">1</span><span class="RktVal">)</span> are not representatives of
|
||
|
BSL expressions. As a result, S-expressions are quite inconvenient for
|
||
|
the designers of interpreters.</p><p>Programmers invented <span style="font-style: italic">parser</span>s to bridge the gap between convenience of
|
||
|
use and implementation. A parser simultaneously checks
|
||
|
whether some piece of data conforms to a data definition and, if it does,
|
||
|
builds a matching element from the chosen class of data. The latter is
|
||
|
called a <span style="font-style: italic">parse tree</span>. If the given data does not conform, a
|
||
|
parser signals an error, much like the checked functions from
|
||
|
<a href="part_one.html#%28part._sec~3ainput-errors%29" data-pltdoc="x">Input Errors</a>.</p><p><a href="part_four.html#%28counter._%28figure._fig~3aparse-bsl-expr%29%29" data-pltdoc="x">Figure <span class="FigureRef">125</span></a> presents a BSL parser for
|
||
|
S-expressions. Specifically, <span class="RktSym">parse</span> consumes an
|
||
|
<a href="part_four.html#%28tech._s._expr%29" class="techoutside" data-pltdoc="x"><span class="techinside">S-expr</span></a> and produces a <span class="RktSym">BSL-expr</span>—<wbr></wbr>if and only if the given
|
||
|
S-expression is the result of quoting a BSL expression that has a
|
||
|
<span class="RktSym">BSL-expr</span> representative.</p><p><a name="(counter._(exercise._ex~3absl-parse))"></a><span style="font-weight: bold">Exercise</span> 349. Create tests for <span class="RktSym">parse</span> until DrRacket tells
|
||
|
you that every element in the definitions area is covered during the test
|
||
|
run. <a href="part_four.html#%28counter._%28exercise._ex~3absl-parse%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._(exercise._ex~3absl-parse2))"></a><span style="font-weight: bold">Exercise</span> 350. What is unusual about the definition of this
|
||
|
program with respect to the design recipe? <a href="part_four.html#%28counter._%28exercise._ex~3absl-parse2%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._(exercise._ex~3absl-parse1))"></a><span style="font-weight: bold">Exercise</span> 351. Design <span class="RktSym">interpreter-expr</span>. The function
|
||
|
accepts S-expressions. If <span class="RktSym">parse</span> recognizes them as
|
||
|
<a href="part_four.html#%28tech._bsl._expr%29" class="techoutside" data-pltdoc="x"><span class="techinside">BSL-expr</span></a>, it produces their value. Otherwise, it signals the same
|
||
|
error as <span class="RktSym">parse</span>. <a href="part_four.html#%28counter._%28exercise._ex~3absl-parse1%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(idx._(gentag._520))"></a>
|
||
|
<a name="(idx._(gentag._521))"></a>
|
||
|
<a name="(idx._(gentag._522))"></a></p><blockquote class="Figure"><blockquote class="Centerfigure"><blockquote class="FigureInside"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_four.html#%28tech._s._expr%29" class="techoutside" data-pltdoc="x"><span class="techinside">S-expr</span></a><span class="RktCmt"> -> </span><a href="part_four.html#%28tech._bsl._expr%29" class="techoutside" data-pltdoc="x"><span class="techinside">BSL-expr</span></a></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">parse</span><span class="hspace"> </span><span class="RktSym">s</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym">atom?</span><span class="hspace"> </span><span class="RktSym">s</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">parse-atom</span><span class="hspace"> </span><span class="RktSym">s</span><span class="RktPn">)</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._else%29%29" class="RktStxLink" data-pltdoc="x">else</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">parse-sl</span><span class="hspace"> </span><span class="RktSym">s</span><span class="RktPn">)</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_four.html#%28tech._sl%29" class="techoutside" data-pltdoc="x"><span class="techinside">SL</span></a><span class="RktCmt"> -> </span><a href="part_four.html#%28tech._bsl._expr%29" class="techoutside" data-pltdoc="x"><span class="techinside">BSL-expr</span></a><span class="RktCmt"> </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">parse-sl</span><span class="hspace"> </span><span class="RktSym">s</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._and%29%29" class="RktStxLink" data-pltdoc="x">and</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">consists-of-3</span><span class="hspace"> </span><span class="RktSym">s</span><span class="RktPn">)</span><span class="hspace"
|
||
|
not have a value if it contains a variable. Indeed, unless we know what
|
||
|
<span class="RktSym">x</span> stands for, it makes no sense to evaluate <span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._%2B%29%29" class="RktValLink" data-pltdoc="x">+</a></span><span class="stt"> </span><span class="RktVal">3</span><span class="stt"> </span><span class="RktSym">x</span><span class="RktPn">)</span>. Hence, one first refinement of the evaluator is to add variables to
|
||
|
the expressions that we wish to evaluate. The assumption is that the
|
||
|
definitions area contains a definition such as
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">x</span><span class="hspace"> </span><span class="RktVal">5</span><span class="RktPn">)</span></p></blockquote></div><div class="SIntrapara">and that programmers evaluate expressions containing <span class="RktSym">x</span> in
|
||
|
the interactions area:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">> </span><span class="RktSym">x</span></td></tr><tr><td><p><span class="RktRes">5</span></p></td></tr><tr><td><span class="stt">> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._%2B%29%29" class="RktValLink" data-pltdoc="x">+</a></span><span class="hspace"> </span><span class="RktSym">x</span><span class="hspace"> </span><span class="RktVal">3</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktRes">8</span></p></td></tr><tr><td><span class="stt">> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._%2A%29%29" class="RktValLink" data-pltdoc="x">*</a></span><span class="hspace"> </span><span class="RktVal">1/2</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._%2A%29%29" class="RktValLink" data-pltdoc="x">*</a></span><span class="hspace"> </span><span class="RktSym">x</span><span class="hspace"> </span><span class="RktVal">3</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktRes">7.5</span></p></td></tr></table></blockquote></div><div class="SIntrapara">Indeed, you could imagine a second definition, say
|
||
|
<span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="stt"> </span><span class="RktSym">y</span><span class="stt"> </span><span class="RktVal">3</span><span class="RktPn">)</span>, and interactions that involve two variables:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._%2B%29%29" class="RktValLink" data-pltdoc="x">+</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._%2A%29%29" class="RktValLink" data-pltdoc="x">*</a></span><span class="hspace"> </span><span class="RktSym">x</span><span class="hspace"> </span><span class="RktSym">x</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._%2A%29%29" class="RktValLink" data-pltdoc="x">*</a></span><span class="hspace"> </span><span class="RktSym">y</span><span class="hspace"> </span><span class="RktSym">y</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></td></tr><tr><td><p><span class="RktRes">34</span></p></td></tr></table></blockquote></div></p><p><div class="SIntrapara">The preceding section implicitly proposes symbols as representations for
|
||
|
variables. After all, if you were to choose quoted S-expressions to
|
||
|
represent expressions with variables, symbols would appear naturally:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">> </span><span class="RktVal">'</span><span class="RktVal">x</span></td></tr><tr><td><p><span class="RktRes">'x</span></p></td></tr><tr><td><span class="stt">> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">*</span><span class="hspace"> </span><span class="RktVal">1/2</span><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">*</span><span class="hspace"> </span><span class="RktVal">x</span><span class="hspace"> </span><span class="RktVal">3</span><span class="RktVal">)</span><span class="RktVal">)</span></td></tr><tr><td><p><span class="RktRes">(list '* 0.5 (list '* 'x 3))</span></p></td></tr></table></blockquote></div><div class="SIntrapara">One obvious alternative is a string, so that <span class="RktVal">"x"</span> would represent
|
||
|
<span class="RktSym">x</span>, but this book is not about designing interpreters, so we stick
|
||
|
with symbols. From this decision, it follows how to modify the data
|
||
|
definition from <a href="part_four.html#%28counter._%28exercise._ex~3absl-dd%29%29" data-pltdoc="x">exercise 345</a>:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">A </span><a name="(tech._bsl._var._expr)"></a><span style="font-style: italic">BSL-var-expr</span><span class="RktCmt"> is one of: </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">–</span><span class="RktCmt"> </span><a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">–</span><span class="RktCmt"> </span><a href="i2-3.html#%28tech._symbol%29" class="techoutside" data-pltdoc="x"><span class="techinside">Symbol</span></a><span class="RktCmt"> </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">–</span><span class="RktCmt"> </span><span class="RktPn">(</span><span class="RktSym">make-add</span><span class="stt"> </span><a href="part_four.html#%28tech._bsl._var._expr%29" class="techoutside" data-pltdoc="x"><span class="techinside">BSL-var-expr</span></a><span class="stt"> </span><a href="part_four.html#%28tech._bsl._var._expr%29" class="techoutside" data-pltdoc="x"><span class="techinside">BSL-var-expr</span></a><span class="RktPn">)</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">–</span><span class="RktCmt"> </span><span class="RktPn">(</span><span class="RktSym">make-mul</span><span class="stt"> </span><a href="part_four.html#%28tech._bsl._var._expr%29" class="techoutside" data-pltdoc="x"><span class="techinside">BSL-var-expr</span></a><span class="stt"> </span><a href="part_four.html#%28tech._bsl._var._expr%29" class="techoutside" data-pltdoc="x"><span class="techinside">BSL-var-expr</span></a><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">We simply add one clause to the data definition.</div></p><p><div class="SIntrapara">As for data examples, the following table shows some BSL expressions
|
||
|
with variables and their <a href="part_four.html#%28tech._bsl._var._expr%29" class="techoutside" data-pltdoc="x"><span class="techinside">BSL-var-expr</span></a> representation:
|
||
|
</div><div class="SIntrapara"><blockquote><table cellspacing="0" cellpadding="0" style="border-collapse: collapse;"><tr><td align="left" style="border-bottom: 1px solid black;"><p><span style="font-weight: bold">BSL expression</span></p></td><td align="left" style="border-bottom: 1px solid black;"><p><span class="hspace"> </span></p></td><td align="left" style="border-bottom: 1px solid black;"><p><span style="font-weight: bold">representation of BSL expression</span></p></td></tr><tr><td align="left"><span class="RktSym">x</span></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><span class="RktVal">'</span><span class="RktVal">x</span></td></tr><tr><td align="left"><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._%2B%29%29" class="RktValLink" data-pltdoc="x">+</a></span><span class="hspace"> </span><span class="RktSym">x</span><span class="hspace"> </span><span class="RktVal">3</span><span class="RktPn">)</span></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><span class="RktPn">(</span><span class="RktSym">make-add</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">x</span><span class="hspace"> </span><span class="RktVal">3</span><span class="RktPn">)</span></td></tr><tr><td align="left"><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._%2A%29%29" class="RktValLink" data-pltdoc="x">*</a></span><span class="hspace"> </span><span class="RktVal">1/2</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._%2A%29%29" class="RktValLink" data-pltdoc="x">*</a></span><span class="hspace"> </span><span class="RktSym">x</span><span class="hspace"> </span><span class="RktVal">3</span><span class="RktPn">)</span><span class="RktPn">)</span></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><span class="RktPn">(</span><span class="RktSym">make-mul</span><span class="hspace"> </span><span class="RktVal">1/2</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">make-mul</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">x</span><span class="hspace"> </span><span class="RktVal">3</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td align="left"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._%2B%29%29" class="RktValLink" data-pltdoc="x">+</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._%2A%29%29" class="RktValLink" data-pltdoc="x">*</a></span><span class="hspace"> </span><span class="RktSym">x</span><span class="hspace"> </span><span class="RktSym">x</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._%2A%29%29" class="RktValLink" data-pltdoc="x">*</a></span><span class="hspace"> </span><span class="RktSym">y</span><span class="hspace"> </span><span clas
|
||
|
results when <span class="RktSym">x</span> is <span class="RktVal">5</span> and <span class="RktSym">y</span> <span class="RktVal">3</span>.</div></p><p>One way to determine the value of variable expressions is to replace all
|
||
|
variables with the values that they represent. This is the way you know
|
||
|
from mathematics classes in school, and it is a perfectly fine way.</p><p><a name="(counter._(exercise._ex~3absl-var-subst))"></a><span style="font-weight: bold">Exercise</span> 352. Design <span class="RktSym">subst</span>. The function consumes a
|
||
|
<a href="part_four.html#%28tech._bsl._var._expr%29" class="techoutside" data-pltdoc="x"><span class="techinside">BSL-var-expr</span></a> <span class="RktSym">ex</span>, a <a href="i2-3.html#%28tech._symbol%29" class="techoutside" data-pltdoc="x"><span class="techinside">Symbol</span></a> <span class="RktSym">x</span>, and a
|
||
|
<a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a> <span class="RktSym">v</span>. It produces a <a href="part_four.html#%28tech._bsl._var._expr%29" class="techoutside" data-pltdoc="x"><span class="techinside">BSL-var-expr</span></a> like
|
||
|
<span class="RktSym">ex</span> with all occurrences of <span class="RktSym">x</span> replaced by <span class="RktSym">v</span>. <a href="part_four.html#%28counter._%28exercise._ex~3absl-var-subst%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._(exercise._ex~3absl-var-numeric))"></a><span style="font-weight: bold">Exercise</span> 353. Design the <span class="RktSym">numeric?</span> function. It
|
||
|
determines whether a <a href="part_four.html#%28tech._bsl._var._expr%29" class="techoutside" data-pltdoc="x"><span class="techinside">BSL-var-expr</span></a> is also a <a href="part_four.html#%28tech._bsl._expr%29" class="techoutside" data-pltdoc="x"><span class="techinside">BSL-expr</span></a>. Here
|
||
|
we assume that your solution to <a href="part_four.html#%28counter._%28exercise._ex~3absl-dd%29%29" data-pltdoc="x">exercise 345</a> is the definition for
|
||
|
<a href="part_four.html#%28tech._bsl._var._expr%29" class="techoutside" data-pltdoc="x"><span class="techinside">BSL-var-expr</span></a> without <a href="i2-3.html#%28tech._symbol%29" class="techoutside" data-pltdoc="x"><span class="techinside">Symbol</span></a>s. <a href="part_four.html#%28counter._%28exercise._ex~3absl-var-numeric%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._(exercise._ex~3absl-var-eval))"></a><span style="font-weight: bold">Exercise</span> 354. Design <span class="RktSym">eval-variable</span>. The checked
|
||
|
function consumes a <span class="RktSym">BSL-var-expr</span> and determines its value if
|
||
|
<span class="RktSym">numeric?</span> yields true for the input. Otherwise it signals an
|
||
|
error.</p><p><div class="SIntrapara">In general, a program defines many constants in the definitions area, and
|
||
|
expressions contain more than one variable. To evaluate such expressions,
|
||
|
we need a representation of the definitions area when it contains a series
|
||
|
of constant definitions. For this exercise we use association lists:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">An </span><a name="(tech._al)"></a><span style="font-style: italic">AL</span><span class="RktCmt"> (short for </span><span style="font-style: italic">association list</span><span class="RktCmt">) is [</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> </span><a href="part_four.html#%28tech._association%29" class="techoutside" data-pltdoc="x"><span class="techinside">Association</span></a><span class="RktCmt">].</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">An </span><a name="(tech._association)"></a><span style="font-style: italic">Association</span><span class="RktCmt"> is a list of two items:</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="stt"> </span><a href="i2-3.html#%28tech._symbol%29" class="techoutside" data-pltdoc="x"><span class="techinside">Symbol</span></a><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="stt"> </span><a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a><span class="stt"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktCmt">.</span></td></tr></table></blockquote></div><div class="SIntrapara">Make up elements of <a href="part_four.html#%28tech._al%29" class="techoutside" data-pltdoc="x"><span class="techinside">AL</span></a>.</div></p><p>Design <span class="RktSym">eval-variable*</span>. The function consumes a <a href="part_four.html#%28tech._bsl._var._expr%29" class="techoutside" data-pltdoc="x"><span class="techinside">BSL-var-expr</span></a>
|
||
|
<span class="RktSym">ex</span> and an association list <span class="RktSym">da</span>. Starting from
|
||
|
<span class="RktSym">ex</span>, it iteratively applies <span class="RktSym">subst</span> to all associations in
|
||
|
<span class="RktSym">da</span>. If <span class="RktSym">numeric?</span> holds for the result, it determines its
|
||
|
value; otherwise it signals the same error as <span class="RktSym">eval-variable</span>.
|
||
|
<span style="font-weight: bold">Hint</span> Think of the given <a href="part_four.html#%28tech._bsl._var._expr%29" class="techoutside" data-pltdoc="x"><span class="techinside">BSL-var-expr</span></a> as an atomic value and
|
||
|
traverse the given association list instead. We provide this hint because
|
||
|
the creation of this function requires a little design knowledge from
|
||
|
<a href="part_four.html#%28part._ch~3asimu%29" data-pltdoc="x">Simultaneous Processing</a>. <a href="part_four.html#%28counter._%28exercise._ex~3absl-var-eval%29%29" class="ex-end" data-pltdoc="x"></a></p><p><span style="font-weight: bold">An environment model</span> <a href="part_four.html#%28counter._%28exercise._ex~3absl-var-eval%29%29" data-pltdoc="x">Exercise 354</a> relies on the
|
||
|
mathematical understanding of constant definitions. If a name is defined
|
||
|
to stand for some value, all occurrences of the name can be replaced with
|
||
|
the value. Substitution performs this replacement once and for all before
|
||
|
the evaluation process even starts.</p><p>An alternative approach, dubbed the <span style="font-style: italic">environment model</span>, is to look
|
||
|
up the value of a variable when needed. The evaluator starts processing
|
||
|
the expression immediately but also carries along the representation of
|
||
|
the definitions area. Every time the evaluator encounters a variable, it
|
||
|
looks in the definitions area for its value and uses it.</p><p><div class="SIntrapara"><a name="(counter._(exercise._ex~3absl-var-eval2))"></a><span style="font-weight: bold">Exercise</span> 355. Design <span class="RktSym">eval-var-lookup</span>. This
|
||
|
function has the same signature as <span class="RktSym">eval-variable*</span>:<a name="(idx._(gentag._523))"></a>
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_four.html#%28tech._bsl._var._expr%29" class="techoutside" data-pltdoc="x"><span class="techinside">BSL-var-expr</span></a><span class="RktCmt"> </span><a href="part_four.html#%28tech._al%29" class="techoutside" data-pltdoc="x"><span class="techinside">AL</span></a><span class="RktCmt"> -> </span><a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">eval-var-lookup</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._e%29%29" class="RktValLink" data-pltdoc="x">e</a></span><span class="hspace"> </span><span class="RktSym">da</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">Instead of using substitution, the function traverses the
|
||
|
expression in the manner that the design recipe for <a href="part_four.html#%28tech._bsl._var._expr%29" class="techoutside" data-pltdoc="x"><span class="techinside">BSL-var-expr</span></a>
|
||
|
suggests. As it descends the expression, it “carries along”
|
||
|
<span class="RktSym">da</span>. When it encounters a symbol <span class="RktSym">x</span>, it uses <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._assq%29%29" class="RktValLink" data-pltdoc="x">assq</a></span>
|
||
|
to look up the value of <span class="RktSym">x</span> in the association list. If there is no
|
||
|
value, <span class="RktSym">eval-var-lookup</span> signals an error. <a href="part_four.html#%28counter._%28exercise._ex~3absl-var-eval2%29%29" class="ex-end" data-pltdoc="x"></a></div></p><h4>21.3<tt> </tt><a name="(part._sec~3ainterpreter-functions)"></a>Interpreting Functions</h4><p>At this point, you understand how to evaluate BSL programs that consist
|
||
|
of constant definitions and variable expressions. Naturally you want to
|
||
|
add function definitions so that you know—<wbr></wbr>at least in principle—<wbr></wbr>how to
|
||
|
deal with all of BSL.</p><p>The goal of this section is to refine the evaluator of
|
||
|
<a href="part_four.html#%28part._sec~3ainterpreter-variables%29" data-pltdoc="x">Interpreting Variables</a> so that it can cope with
|
||
|
functions. Since function definitions show up in the definitions area,
|
||
|
another way to describe the refined evaluator is to say that it simulates
|
||
|
DrRacket when the definitions area contains a number of function definitions
|
||
|
and a programmer enters an expression in the interactions area that
|
||
|
contains uses of these functions.</p><p>For simplicity, let’s assume that all functions in the definitions area
|
||
|
consume one argument and that there is only one such definition. The
|
||
|
necessary domain knowledge dates back to school where you learned that
|
||
|
<span style="font-style: italic">f</span>(<span style="font-style: italic">x</span>)<span style="font-style: italic"> = e</span> represents the definition of function <span style="font-style: italic">f</span>, that
|
||
|
<span style="font-style: italic">f</span>(<span style="font-style: italic">a</span>)<span style="font-style: italic"></span> represents the application of <span style="font-style: italic">f</span> to <span style="font-style: italic">a</span>, and that
|
||
|
to evaluate the latter, you substitute <span style="font-style: italic">a</span> for <span style="font-style: italic">x</span> in
|
||
|
<span style="font-style: italic">e</span>. As it turns out, the evaluation of function applications in a
|
||
|
language such as BSL works mostly like that, too.</p><p>Before tackling the following exercises, you may wish to refresh your
|
||
|
knowledge of the terminology concerning functions as presented in
|
||
|
intermezzo 1. Most of the time, algebra courses gloss over
|
||
|
this aspect of mathematics, but a precise use and understanding of
|
||
|
terminology is needed when you wish to solve these problems.</p><p><a name="(counter._(exercise._ex~3absl-one-def))"></a><span style="font-weight: bold">Exercise</span> 356. Extend the data representation of
|
||
|
<a href="part_four.html#%28part._sec~3ainterpreter-variables%29" data-pltdoc="x">Interpreting Variables</a> to include the application of a
|
||
|
programmer-defined function. Recall that a function application consists
|
||
|
of two pieces: a name and an expression. The former is the name of the
|
||
|
function that is applied; the latter is the argument.</p><p>Represent these expressions: <span class="RktPn">(</span><span class="RktSym">k</span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._%2B%29%29" class="RktValLink" data-pltdoc="x">+</a></span><span class="stt"> </span><span class="RktVal">1</span><span class="stt"> </span><span class="RktVal">1</span><span class="RktPn">)</span><span class="RktPn">)</span>, <span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._%2A%29%29" class="RktValLink" data-pltdoc="x">*</a></span><span class="stt"> </span><span class="RktVal">5</span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym">k</span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._%2B%29%29" class="RktValLink" data-pltdoc="x">+</a></span><span class="stt"> </span><span class="RktVal">1</span><span class="stt"> </span><span class="RktVal">1</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span>, <span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._%2A%29%29" class="RktValLink" data-pltdoc="x">*</a></span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym">i</span><span class="stt"> </span><span class="RktVal">5</span><span class="RktPn">)</span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym">k</span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._%2B%29%29" class="RktValLink" data-pltdoc="x">+</a></span><span class="stt"> </span><span class="RktVal">1</span><span class="stt"> </span><span class="RktVal">1</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span>. We refer to this newly defined
|
||
|
class of data as <a name="(tech._bsl._fun._expr)"></a><span style="font-style: italic">BSL-fun-expr</span>. <a href="part_four.html#%28counter._%28exercise._ex~3absl-one-def%29%29" class="ex-end" data-pltdoc="x"></a></p><p><div class="SIntrapara"><a name="(counter._(exercise._ex~3absl-eval-def1))"></a><span style="font-weight: bold">Exercise</span> 357. Design <span class="RktSym">eval-definition1</span>. The
|
||
|
function consumes four arguments:
|
||
|
</div><div class="SIntrapara"><ol><li><p>a <a href="part_four.html#%28tech._bsl._fun._expr%29" class="techoutside" data-pltdoc="x"><span class="techinside">BSL-fun-expr</span></a> <span class="RktSym">ex</span>;</p></li><li><p>a symbol <span class="RktSym">f</span>, which represents a function name;</p></li><li><p>a symbol <span class="RktSym">x</span>, which represents the functions’ parameter; and</p></li><li><p>a <a href="part_four.html#%28tech._bsl._fun._expr%29" class="techoutside" data-pltdoc="x"><span class="techinside">BSL-fun-expr</span></a> <span class="RktSym">b</span>, which represents the function’s body.</p></li></ol></div><div class="SIntrapara">It determines the value of <span class="RktSym">ex</span>. When <span class="RktSym">eval-definition1</span>
|
||
|
encounters an application of <span class="RktSym">f</span> to some argument, it
|
||
|
</div><div class="SIntrapara"><ol><li><p>evaluates the argument,</p></li><li><p>substitutes the value of the argument for <span class="RktSym">x</span> in <span class="RktSym">b</span>; and</p></li><li><p>finally evaluates the resulting expression with <span class="RktSym">eval-definition1</span>.</p></li></ol></div><div class="SIntrapara">Here is how to express the steps as code, assuming <span class="RktSym">arg</span> is the
|
||
|
argument of the function application:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._local%29%29" class="RktStxLink" data-pltdoc="x">local</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">value</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">eval-definition1</span><span class="hspace"> </span><span class="RktSym">arg</span><span class="hspace"> </span><span class="RktSym">f</span><span class="hspace"> </span><span class="RktSym">x</span><span class="hspace"> </span><span class="RktSym">b</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">plugd</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">subst</span><span class="hspace"> </span><span class="RktSym">b</span><span class="hspace"> </span><span class="RktSym">x</span><span class="hspace"> </span><span class="RktSym">value</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">eval-definition1</span><span class="hspace"> </span><span class="RktSym">plugd</span><span class="hspace"> </span><span class="RktSym">f</span><span class="hspace"> </span><span class="RktSym">x</span><span class="hspace"> </span><span class="RktSym">b</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">Notice that this line uses a form of recursion that has not been
|
||
|
covered. The proper design of such functions is discussed in <a href="part_five.html" data-pltdoc="x">Generative Recursion</a>.</div></p><p>If <span class="RktSym">eval-definition1</span> encounters a variable, it signals the same
|
||
|
error as <span class="RktSym">eval-variable</span> from <a href="part_four.html#%28counter._%28exercise._ex~3absl-var-eval%29%29" data-pltdoc="x">exercise 354</a>. It also
|
||
|
signals an error for function applications that refer to a function name
|
||
|
other than <span class="RktSym">f</span>.</p><p><span style="font-weight: bold">Warning</span> The use of this uncovered form of recursion introduces a new
|
||
|
element into your computations: non-termination. That is, a program may
|
||
|
run forever instead of delivering a result or signaling an error. If you
|
||
|
followed the design recipes of the first four parts, you cannot write down
|
||
|
such programs. For fun, construct an input for <span class="RktSym">eval-definition1</span>
|
||
|
that causes it to run forever. Use <span class="emph">STOP</span> to terminate the
|
||
|
program. <a href="part_four.html#%28counter._%28exercise._ex~3absl-eval-def1%29%29" class="ex-end" data-pltdoc="x"></a></p><p>For an evaluator that mimics the interactions area, we need a representation
|
||
|
of the definitions area. We assume that it is a list of definitions.</p><p><div class="SIntrapara"><a name="(counter._(exercise._ex~3absl-prog-dd))"></a><span style="font-weight: bold">Exercise</span> 358. Provide a structure type and a data
|
||
|
definition for function definitions. Recall that such a definition
|
||
|
has three essential attributes:
|
||
|
</div><div class="SIntrapara"><ol><li><p>the function’s name, which is represented with a symbol;</p></li><li><p>the function’s parameter, which is also a name; and</p></li><li><p>the function’s body, which is a variable expression.</p></li></ol></div><div class="SIntrapara">We use <a name="(tech._bsl._fun._def)"></a><span style="font-style: italic">BSL-fun-def</span> to refer to this class of data.</div></p><p><div class="SIntrapara">Use your data definition to represent these BSL function definitions:
|
||
|
</div><div class="SIntrapara"><ol><li><p><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym">f</span><span class="stt"> </span><span class="RktSym">x</span><span class="RktPn">)</span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._%2B%29%29" class="RktValLink" data-pltdoc="x">+</a></span><span class="stt"> </span><span class="RktVal">3</span><span class="stt"> </span><span class="RktSym">x</span><span class="RktPn">)</span><span class="RktPn">)</span></p></li><li><p><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym">g</span><span class="stt"> </span><span class="RktSym">y</span><span class="RktPn">)</span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym">f</span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._%2A%29%29" class="RktValLink" data-pltdoc="x">*</a></span><span class="stt"> </span><span class="RktVal">2</span><span class="stt"> </span><span class="RktSym">y</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></p></li><li><p><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym">h</span><span class="stt"> </span><span class="RktSym">v</span><span class="RktPn">)</span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._%2B%29%29" class="RktValLink" data-pltdoc="x">+</a></span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym">f</span><span class="stt"> </span><span class="RktSym">v</span><span class="RktPn">)</span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym">g</span><span class="stt"> </span><span class="RktSym">v</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></p></li></ol></div></p><p>Next, define the class <a name="(tech._bsl._fun._def*)"></a><span style="font-style: italic">BSL-fun-def*</span> to represent a definitions area
|
||
|
that consists of a number of one-argument function definitions. Translate the
|
||
|
definitions area that defines <span class="RktSym">f</span>, <span class="RktSym">g</span>, and <span class="RktSym">h</span> into
|
||
|
your data representation and name it <span class="RktSym">da-fgh</span>.</p><p><div class="SIntrapara">Finally, work on the following wish:<a name="(idx._(gentag._524))"></a>
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_four.html#%28tech._bsl._fun._def%2A%29" class="techoutside" data-pltdoc="x"><span class="techinside">BSL-fun-def*</span></a><span class="RktCmt"> </span><a href="i2-3.html#%28tech._symbol%29" class="techoutside" data-pltdoc="x"><span class="techinside">Symbol</span></a><span class="RktCmt"> -> </span><a href="part_four.html#%28tech._bsl._fun._def%29" class="techoutside" data-pltdoc="x"><span class="techinside">BSL-fun-def</span></a></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">retrieves the definition of </span><span class="RktSym">f</span><span class="RktCmt"> in </span><span class="RktSym">da</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">signals an error if there is none</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._check-expect%29%29" class="RktStxLink" data-pltdoc="x">check-expect</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">lookup-def</span><span class="hspace"> </span><span class="RktSym">da-fgh</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">g</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">g</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">lookup-def</span><span class="hspace"> </span><span class="RktSym">da</span><span class="hspace"> </span><span class="RktSym">f</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">Looking up a definition is needed for the evaluation of applications. <a href="part_four.html#%28counter._%28exercise._ex~3absl-prog-dd%29%29" class="ex-end" data-pltdoc="x"></a></div></p><p><a name="(counter._(exercise._ex~3absl-eval-def))"></a><span style="font-weight: bold">Exercise</span> 359. Design <span class="RktSym">eval-function*</span>. The function
|
||
|
consumes <span class="RktSym">ex</span>, a <a href="part_four.html#%28tech._bsl._fun._expr%29" class="techoutside" data-pltdoc="x"><span class="techinside">BSL-fun-expr</span></a>, and <span class="RktSym">da</span>, a
|
||
|
<a href="part_four.html#%28tech._bsl._fun._def%2A%29" class="techoutside" data-pltdoc="x"><span class="techinside">BSL-fun-def*</span></a> representation of a definitions area. It produces the
|
||
|
result that DrRacket shows if you evaluate <span class="RktSym">ex</span> in the interactions
|
||
|
area, assuming the definitions area contains <span class="RktSym">da</span>.</p><p><div class="SIntrapara">The function works like <span class="RktSym">eval-definition1</span> from <a href="part_four.html#%28counter._%28exercise._ex~3absl-eval-def1%29%29" data-pltdoc="x">exercise 357</a>.
|
||
|
For an application of some function <span class="RktSym">f</span>, it
|
||
|
</div><div class="SIntrapara"><ol><li><p>evaluates the argument;</p></li><li><p>looks up the definition of <span class="RktSym">f</span> in the <a href="part_four.html#%28tech._bsl._fun._def%29" class="techoutside" data-pltdoc="x"><span class="techinside">BSL-fun-def</span></a>
|
||
|
representation of <span class="RktSym">da</span>, which comes with a parameter and a body;</p></li><li><p>substitutes the value of the argument for the function parameter in
|
||
|
the function’s body; and</p></li><li><p>evaluates the new expression via recursion.</p></li></ol></div><div class="SIntrapara">Like DrRacket, <span class="RktSym">eval-function*</span> signals an error when it encounters a
|
||
|
variable or function name without definition in the definitions area. <a href="part_four.html#%28counter._%28exercise._ex~3absl-eval-def%29%29" class="ex-end" data-pltdoc="x"></a></div></p><h4>21.4<tt> </tt><a name="(part._sec~3ainterpreter-all)"></a>Interpreting Everything</h4><p><div class="SIntrapara">Take a look at the following BSL program: <a name="(idx._(gentag._525))"></a> <a name="(idx._(gentag._526))"></a>
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">close-to-pi</span><span class="hspace"> </span><span class="RktVal">3.14</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">area-of-circle</span><span class="hspace"> </span><span class="RktSym">r</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._%2A%29%29" class="RktValLink" data-pltdoc="x">*</a></span><span class="hspace"> </span><span class="RktSym">close-to-pi</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._%2A%29%29" class="RktValLink" data-pltdoc="x">*</a></span><span class="hspace"> </span><span class="RktSym">r</span><span class="hspace"> </span><span class="RktSym">r</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">volume-of-10-cylinder</span><span class="hspace"> </span><span class="RktSym">r</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._%2A%29%29" class="RktValLink" data-pltdoc="x">*</a></span><span class="hspace"> </span><span class="RktVal">10</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">area-of-circle</span><span class="hspace"> </span><span class="RktSym">r</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">Think of these definitions as the definitions area in DrRacket. After you
|
||
|
click <span class="emph">RUN</span>, you can evaluate expressions involving <span class="RktSym">close-to-pi</span>,
|
||
|
<span class="RktSym">area-of-circle</span>, and <span class="RktSym">volume-of-10-cylinder</span> in the
|
||
|
interactions area:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">> </span><span class="RktPn">(</span><span class="RktSym">area-of-circle</span><span class="hspace"> </span><span class="RktVal">1</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktRes">#i3.14</span></p></td></tr><tr><td><span class="stt">> </span><span class="RktPn">(</span><span class="RktSym">volume-of-10-cylinder</span><span class="hspace"> </span><span class="RktVal">1</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktRes">#i31.400000000000002</span></p></td></tr><tr><td><span class="stt">> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._%2A%29%29" class="RktValLink" data-pltdoc="x">*</a></span><span class="hspace"> </span><span class="RktVal">3</span><span class="hspace"> </span><span class="RktSym">close-to-pi</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktRes">#i9.42</span></p></td></tr></table></blockquote></div><div class="SIntrapara">The goal of this section is to refine your evaluator again so that
|
||
|
it can mimic this much of DrRacket.</div></p><p><a name="(counter._(exercise._ex~3absl-da-all))"></a><span style="font-weight: bold">Exercise</span> 360. Formulate a data definition for the
|
||
|
representation of DrRacket’s definitions area. Concretely, the data
|
||
|
representation should work for a sequence that freely mixes constant
|
||
|
definitions and one-argument function definitions. Make sure you can
|
||
|
represent the definitions area consisting of three definitions at the
|
||
|
beginning of this section. We name this class of data
|
||
|
<a name="(tech._bsl._da._all)"></a><span style="font-style: italic">BSL-da-all</span>.</p><p>Design the function <span class="RktSym">lookup-con-def</span>. It consumes a
|
||
|
<a href="part_four.html#%28tech._bsl._da._all%29" class="techoutside" data-pltdoc="x"><span class="techinside">BSL-da-all</span></a> <span class="RktSym">da</span> and a symbol <span class="RktSym">x</span>. It produces the
|
||
|
representation of a constant definition whose name is <span class="RktSym">x</span>, if such
|
||
|
a piece of data exists in <span class="RktSym">da</span>; otherwise the function signals an
|
||
|
error saying that no such constant definition can be found.</p><p>Design the function <span class="RktSym">lookup-fun-def</span>. It consumes a
|
||
|
<a href="part_four.html#%28tech._bsl._da._all%29" class="techoutside" data-pltdoc="x"><span class="techinside">BSL-da-all</span></a> <span class="RktSym">da</span> and a symbol <span class="RktSym">f</span>. It produces the
|
||
|
representation of a function definition whose name is <span class="RktSym">f</span>, if such
|
||
|
a piece of data exists in <span class="RktSym">da</span>; otherwise the function signals an
|
||
|
error saying that no such function definition can be found. <a href="part_four.html#%28counter._%28exercise._ex~3absl-da-all%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._(exercise._ex~3absl-eval-all))"></a><span style="font-weight: bold">Exercise</span> 361. Design <span class="RktSym">eval-all</span>. Like
|
||
|
<span class="RktSym">eval-function*</span> from <a href="part_four.html#%28counter._%28exercise._ex~3absl-eval-def%29%29" data-pltdoc="x">exercise 359</a>, this function
|
||
|
consumes the representation of an expression and a definitions area. It
|
||
|
produces the same value that DrRacket shows if the expression is entered at
|
||
|
the prompt in the interactions area and the definitions area contains the
|
||
|
appropriate definitions. <span style="font-weight: bold">Hint</span> Your <span class="RktSym">eval-all</span> function should
|
||
|
process variables in the given expression like <span class="RktSym">eval-var-lookup</span> in
|
||
|
<a href="part_four.html#%28counter._%28exercise._ex~3absl-var-eval2%29%29" data-pltdoc="x">exercise 355</a>. <a href="part_four.html#%28counter._%28exercise._ex~3absl-eval-all%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._(exercise._ex~3absl-all-sexpr))"></a><span style="font-weight: bold">Exercise</span> 362. It is cumbersome to enter the structure-based
|
||
|
data representation of BSL expressions and a definitions area. As
|
||
|
the end of <a href="part_four.html#%28part._sec~3ainterpreter%29" data-pltdoc="x">Interpreting Expressions</a> demonstrates, it is much easier to
|
||
|
quote expressions and (lists of) definitions.</p><p>Design a function <span class="RktSym">interpreter</span>. It consumes an <span class="RktSym">S-expr</span> and
|
||
|
an <span class="RktSym">Sl</span>. The former is supposed to represent an expression and the
|
||
|
latter a list of definitions. The function parses both with the
|
||
|
appropriate parsing functions and then uses <span class="RktSym">eval-all</span> from
|
||
|
<a href="part_four.html#%28counter._%28exercise._ex~3absl-eval-all%29%29" data-pltdoc="x">exercise 361</a> to evaluate the expression. <span style="font-weight: bold">Hint</span> You must
|
||
|
adapt the ideas of <a href="part_four.html#%28counter._%28exercise._ex~3absl-parse2%29%29" data-pltdoc="x">exercise 350</a> to create a parser for
|
||
|
definitions and lists of definitions. <a href="part_four.html#%28counter._%28exercise._ex~3absl-all-sexpr%29%29" class="ex-end" data-pltdoc="x"></a></p><p>At this point, you know a lot about interpreting BSL. Here are some of
|
||
|
the missing pieces: <a href="part_one.html#%28tech._boolean%29" class="techoutside" data-pltdoc="x"><span class="techinside">Boolean</span></a>s with <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span> or <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._if%29%29" class="RktStxLink" data-pltdoc="x">if</a></span>;
|
||
|
<a href="part_one.html#%28tech._string%29" class="techoutside" data-pltdoc="x"><span class="techinside">String</span></a>s and such operations as <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._string-length%29%29" class="RktValLink" data-pltdoc="x">string-length</a></span> or
|
||
|
<span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._string-append%29%29" class="RktValLink" data-pltdoc="x">string-append</a></span>; and lists with <span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span>, <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._empty~3f%29%29" class="RktValLink" data-pltdoc="x">empty?</a></span>,
|
||
|
<span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span>, <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons~3f%29%29" class="RktValLink" data-pltdoc="x">cons?</a></span>, <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._first%29%29" class="RktValLink" data-pltdoc="x">first</a></span>, <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._rest%29%29" class="RktValLink" data-pltdoc="x">rest</a></span>; and so
|
||
|
on. Once your evaluator can cope with all these, it is basically complete
|
||
|
because your evaluators already know how to interpret recursive
|
||
|
functions. Now when we say “trust us, you know how to design these
|
||
|
refinements,” we mean it.</p><h3>22<tt> </tt><a name="(part._ch~3amoney-sexp)"></a>Project: The Commerce of XML</h3><p>XML is a widely used data language. One use concerns message exchanges
|
||
|
between programs running on different computers. For example, when you
|
||
|
point your web browser at a web site, you are connecting a program on your
|
||
|
computer to a program on another computer, and the latter sends XML data
|
||
|
to the former. Once the browser receives the XML data, it renders it as an
|
||
|
image on your computer’s monitor.</p><p><div class="SIntrapara">The following comparison illustrates this idea with a concrete example:
|
||
|
</div><div class="SIntrapara"><blockquote><table cellspacing="0" cellpadding="0" style="border-collapse: collapse;"><tr><td align="left" style="border-bottom: 1px solid black;"><p><span style="font-weight: bold">XML data</span></p></td><td align="left" style="border-bottom: 1px solid black;"><p><span class="hspace"> </span></p></td><td align="left" style="border-bottom: 1px solid black;"><p><span style="font-weight: bold">rendered in a browser</span></p></td></tr><tr><td align="left" valign="bottom"><table cellspacing="0" cellpadding="0"><tr><td><p><span class="stt"><ul></span></p></td></tr><tr><td><p><span class="hspace"> </span><span class="stt"><li> hello </li></span></p></td></tr><tr><td><p><span class="hspace"> </span><span class="stt"><li> <ul> </span></p></td></tr><tr><td><p><span class="hspace"> </span><span class="stt"><li> one </li></span></p></td></tr><tr><td><p><span class="hspace"> </span><span class="stt"><li> two </li></span></p></td></tr><tr><td><p><span class="hspace"> </span><span class="stt"></ul></span></p></td></tr><tr><td><p><span class="hspace"> </span><span class="stt"></li></span></p></td></tr><tr><td><p><span class="hspace"> </span><span class="stt"><li> world </li></span></p></td></tr><tr><td><p><span class="hspace"> </span><span class="stt"><li> good bye </li></span></p></td></tr><tr><td><p><span class="stt"></ul></span></p></td></tr></table></td><td align="left" valign="bottom"><p><span class="hspace"> </span></p></td><td align="left" valign="bottom"><p><img src="xml-example.png" alt="" width="100" height="110"/></p></td></tr></table></blockquote></div><div class="SIntrapara">On the left, you see a piece of XML data that a web site may send to your
|
||
|
web browser. On the right, you see how one popular browser renders this
|
||
|
snippet graphically.</div></p><p>This chapter explains the basics of processing XML as another design
|
||
|
exercise concerning intertwined data definitions and <a name="(idx._(gentag._527))"></a>iterative
|
||
|
refinement. The next section starts with an informal comparison of
|
||
|
S-expressions and XML data and uses it to formulate a full-fledged
|
||
|
data<span class="refelem"><span class="refcolumn"><span class="refcontent">If you think XML is too
|
||
|
old-fashioned for 2022, feel free to redo the exercise for JSON or
|
||
|
some other modern data exchange format. The design principles remain the
|
||
|
same.</span></span></span> definition. The remaining sections explain with examples how to
|
||
|
process an S-expression of XML data.</p><h4>22.1<tt> </tt><a name="(part._sec~3axml)"></a>XML as S-expressions</h4><p><div class="SIntrapara">The most basic piece of XML data looks like this:
|
||
|
</div><div class="SIntrapara"><blockquote><table cellspacing="0" cellpadding="0" class="SVerbatim"><tr><td><p><span class="stt"><machine> </machine></span></p></td></tr></table></blockquote></div><div class="SIntrapara">It is called an <span style="font-style: italic">element</span> and “machine” is the name of the
|
||
|
element. The two parts of the element are like parentheses that delimit
|
||
|
the <span style="font-style: italic">content</span> of an element. When there is no content between the
|
||
|
two parts—<wbr></wbr>other than white space—<wbr></wbr>XML allows a short-hand:
|
||
|
</div><div class="SIntrapara"><blockquote><table cellspacing="0" cellpadding="0" class="SVerbatim"><tr><td><p><span class="stt"><machine /></span></p></td></tr></table></blockquote></div><div class="SIntrapara">But, as far as we are concerned here, this short-hand is equivalent to
|
||
|
the explicitly bracketed version.</div></p><p><div class="SIntrapara">From an S-expression perspective, an XML element
|
||
|
is a <span style="font-weight: bold">named</span> pair of parentheses that surround some content.<span class="refelem"><span class="refcolumn"><span class="refcontent">Racket’s
|
||
|
<span class="stt">xml</span> library represents XML with structures as well as S-expressions.</span></span></span> And
|
||
|
indeed, representing the above with an S-expression is quite natural:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">machine</span><span class="RktVal">)</span></p></blockquote></div><div class="SIntrapara">This piece of data has the opening and closing parentheses, and it comes
|
||
|
with space to embed content.</div></p><p><div class="SIntrapara">Here is a piece of XML data with content:
|
||
|
</div><div class="SIntrapara"><blockquote><table cellspacing="0" cellpadding="0" class="SVerbatim"><tr><td><p><span class="stt"><machine><action /></machine></span></p></td></tr></table></blockquote></div><div class="SIntrapara">Remember that the <span class="stt"><action /></span> part is a short-hand, meaning we are
|
||
|
really looking at this piece of data:
|
||
|
</div><div class="SIntrapara"><blockquote><table cellspacing="0" cellpadding="0" class="SVerbatim"><tr><td><p><span class="stt"><machine><action></action></machine></span></p></td></tr></table></blockquote></div><div class="SIntrapara">In general, the content of an XML element is a series of XML elements:
|
||
|
</div><div class="SIntrapara"><blockquote><table cellspacing="0" cellpadding="0" class="SVerbatim"><tr><td><p><span class="stt"><machine><action /><action /><action /></machine></span></p></td></tr></table></blockquote></div><div class="SIntrapara">Stop! Expand the short-hand for <span class="stt"><action /></span> before you continue.</div></p><p><div class="SIntrapara">The S-expression representation continues to look simple. Here is the first
|
||
|
one:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">machine</span><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">action</span><span class="RktVal">)</span><span class="RktVal">)</span></p></blockquote></div><div class="SIntrapara">And this is the representation for the second one:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">machine</span><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">action</span><span class="RktVal">)</span><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">action</span><span class="RktVal">)</span><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">action</span><span class="RktVal">)</span><span class="RktVal">)</span></p></blockquote></div></p><p><div class="SIntrapara">When you look at the piece of XML data with a sequence of three <span class="stt"><action /></span>
|
||
|
elements as its content, you realize that you may wish to distinguish such
|
||
|
elements from each other. To this end, XML elements come with
|
||
|
<span style="font-style: italic">attributes</span>. For example,
|
||
|
</div><div class="SIntrapara"><blockquote><table cellspacing="0" cellpadding="0" class="SVerbatim"><tr><td><p><span class="stt"><machine initial="red"></machine></span></p></td></tr></table></blockquote></div><div class="SIntrapara">is the “machine” element equipped with one attribute whose
|
||
|
<span style="font-style: italic">name</span> is “initial” and whose value is “red” between string
|
||
|
quotes. Here is a complex XML element with nested elements that have
|
||
|
attributes, too:
|
||
|
</div><div class="SIntrapara"><blockquote><table cellspacing="0" cellpadding="0" class="SVerbatim"><tr><td><p><span class="stt"><machine initial="red"></span></p></td></tr><tr><td><p><span class="stt"></span><span class="hspace"> </span><span class="stt"><action state="red"</span><span class="hspace"> </span><span class="stt">next="green" /></span></p></td></tr><tr><td><p><span class="stt"></span><span class="hspace"> </span><span class="stt"><action state="green"</span><span class="hspace"> </span><span class="stt">next="yellow" /></span></p></td></tr><tr><td><p><span class="stt"></span><span class="hspace"> </span><span class="stt"><action state="yellow" next="red" /></span></p></td></tr><tr><td><p><span class="stt"></machine></span></p></td></tr></table></blockquote></div><div class="SIntrapara">We use blanks, indentation, and line breaks to make the element readable,
|
||
|
but this white space has no meaning for our XML data here.</div></p><p><div class="SIntrapara">Naturally, S-expressions for these “machine” elements look much like
|
||
|
their XML cousins:<span class="refelem"><span class="refcolumn"><span class="refcontent">XML is 40 years younger than S-expressions.</span></span></span>
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">machine</span><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">(</span><span class="RktVal">initial</span><span class="hspace"> </span><span class="RktVal">"red"</span><span class="RktVal">)</span><span class="RktVal">)</span><span class="RktVal">)</span></p></blockquote></div><div class="SIntrapara">To add attributes to an element, we use a list of lists where each of the
|
||
|
latter contains two items: a symbol and a string. The symbol represents
|
||
|
the name of the attribute and the string its value. This idea naturally
|
||
|
applies to complex forms of XML data, too:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">machine</span><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">(</span><span class="RktVal">initial</span><span class="hspace"> </span><span class="RktVal">"red"</span><span class="RktVal">)</span><span class="RktVal">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">action</span><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">(</span><span class="RktVal">state</span><span class="hspace"> </span><span class="RktVal">"red"</span><span class="RktVal">)</span><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">next</span><span class="hspace"> </span><span class="RktVal">"green"</span><span class="RktVal">)</span><span class="RktVal">)</span><span class="RktVal">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">action</span><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">(</span><span class="RktVal">state</span><span class="hspace"> </span><span class="RktVal">"green"</span><span class="RktVal">)</span><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">next</span><span class="hspace"> </span><span class="RktVal">"yellow"</span><span class="RktVal">)</span><span class="RktVal">)</span><span class="RktVal">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">action</span><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">(</span><span class="RktVal">state</span><span class="hspace"> </span><span class="RktVal">"yellow"</span><span class="RktVal">)</span><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">next</span><span class="hspace"> </span><span class="RktVal">"red"</span><span class="RktVal">)</span><span class="RktVal">)</span><span class="RktVal">)</span><span class="RktVal">)</span></td></tr></table></blockquote></div><div class="SIntrapara">For now note how the attributes are marked by two opening
|
||
|
parentheses and the remaining list of (representations of) XML elements
|
||
|
has one opening parenthesis.</div></p><p>You may recall the idea from <a href="i2-3.html" data-pltdoc="x">Intermezzo 2: Quote, Unquote</a>, which uses S-expressions to
|
||
|
represent XHTML, a special dialect of XML. In particular, the intermezzo
|
||
|
shows how easily a programmer can write down nontrivial XML data and even
|
||
|
templates of XML representations using <span class="RktSym">backquote</span> and
|
||
|
<span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._unquote%29%29" class="RktStxLink" data-pltdoc="x">unquote</a></span>. Of course, <a href="part_four.html#%28part._sec~3ainterpreter%29" data-pltdoc="x">Interpreting Expressions</a> points out that you
|
||
|
need a parser to determine whether any given S-expression is a
|
||
|
representation of XML data, and a parser is a complex and unusual kind of
|
||
|
function.</p><p><div class="SIntrapara">Nevertheless, we choose to go with a representation of XML based on
|
||
|
S-expressions to demonstrate the usefulness of this old, poetic idea in
|
||
|
practical terms. We proceed gradually to work out a data
|
||
|
definition, putting <a name="(idx._(gentag._528))"></a>iterative refinement to work. Here is a first attempt:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">An </span><a name="(tech._xexpr..v0)"></a><span style="font-style: italic">Xexpr.v0</span><span class="RktCmt"> (short for </span><span style="font-style: italic">X-expression</span><span class="RktCmt">) is a one-item list:</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="stt"> </span><a href="i2-3.html#%28tech._symbol%29" class="techoutside" data-pltdoc="x"><span class="techinside">Symbol</span></a><span class="stt"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">This is the “named parentheses” idea from the beginning of this
|
||
|
section. Equipping this element representation with content is easy:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">An </span><a name="(tech._xexpr..v1)"></a><span style="font-style: italic">Xexpr.v1</span><span class="RktCmt"> is a list:</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="stt"> </span><a href="i2-3.html#%28tech._symbol%29" class="techoutside" data-pltdoc="x"><span class="techinside">Symbol</span></a><span class="stt"> </span><span class="RktPn">[</span><span class="RktSym">List-of</span><span class="stt"> </span><a href="part_four.html#%28tech._xexpr..v1%29" class="techoutside" data-pltdoc="x"><span class="techinside">Xexpr.v1</span></a><span class="RktPn">]</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">The symbolic name becomes the first item on a list that otherwise consists
|
||
|
of XML element representatives.</div></p><p><div class="SIntrapara">The last refinement step is to add attributes. Since the attributes in an
|
||
|
XML element are optional, the revised data definition has two clauses:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">An </span><a name="(tech._xexpr..v2)"></a><span style="font-style: italic">Xexpr.v2</span><span class="RktCmt"> is a list: </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">–</span><span class="RktCmt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="stt"> </span><a href="i2-3.html#%28tech._symbol%29" class="techoutside" data-pltdoc="x"><span class="techinside">Symbol</span></a><span class="stt"> </span><span style="font-style: italic">Body</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">–</span><span class="RktCmt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="stt"> </span><a href="i2-3.html#%28tech._symbol%29" class="techoutside" data-pltdoc="x"><span class="techinside">Symbol</span></a><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="stt"> </span><span class="RktPn">[</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="stt"> </span><a href="part_four.html#%28tech._attribute%29" class="techoutside" data-pltdoc="x"><span class="techinside">Attribute</span></a><span class="RktPn">]</span><span class="stt"> </span><span style="font-style: italic">Body</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">where </span><span style="font-style: italic">Body</span><span class="RktCmt"> is short for [</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> </span><a href="part_four.html#%28tech._xexpr..v2%29" class="techoutside" data-pltdoc="x"><span class="techinside">Xexpr.v2</span></a><span class="RktCmt">]</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">An </span><a name="(tech._attribute)"></a><span style="font-style: italic">Attribute</span><span class="RktCmt"> is a list of two items:</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="stt"> </span><a href="i2-3.html#%28tech._symbol%29" class="techoutside" data-pltdoc="x"><span class="techinside">Symbol</span></a><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="stt"> </span><a href="part_one.html#%28tech._string%29" class="techoutside" data-pltdoc="x"><span class="techinside">String</span></a><span class="stt"> <
|
||
|
<a href="i2-3.html#%28tech._symbol%29" class="techoutside" data-pltdoc="x"><span class="techinside">Symbol</span></a>, but some are followed by a list of attributes and some by
|
||
|
just a list of <a href="part_four.html#%28tech._xexpr..v2%29" class="techoutside" data-pltdoc="x"><span class="techinside">Xexpr.v2</span></a>s. Reformulate the definition of
|
||
|
<a href="part_four.html#%28tech._xexpr..v2%29" class="techoutside" data-pltdoc="x"><span class="techinside">Xexpr.v2</span></a> to isolate the common beginning and highlight the different
|
||
|
kinds of endings.</p><p>Eliminate the use of <a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a> from <a href="part_four.html#%28tech._xexpr..v2%29" class="techoutside" data-pltdoc="x"><span class="techinside">Xexpr.v2</span></a>. <a href="part_four.html#%28counter._%28exercise._ex~3axml-no-list-of%29%29" class="ex-end" data-pltdoc="x"></a></p><p><div class="SIntrapara"><a name="(counter._(exercise._ex~3axml-represent))"></a><span style="font-weight: bold">Exercise</span> 364. Represent this XML data as elements of <a href="part_four.html#%28tech._xexpr..v2%29" class="techoutside" data-pltdoc="x"><span class="techinside">Xexpr.v2</span></a>:
|
||
|
</div><div class="SIntrapara"><ol><li><p><span class="stt"><transition from="seen-e" to="seen-f" /></span></p></li><li><p><span class="stt"><ul><li><word /><word /></li><li><word /></li></ul></span></p></li></ol></div><div class="SIntrapara">Which one could be represented in <a href="part_four.html#%28tech._xexpr..v0%29" class="techoutside" data-pltdoc="x"><span class="techinside">Xexpr.v0</span></a> or <a href="part_four.html#%28tech._xexpr..v1%29" class="techoutside" data-pltdoc="x"><span class="techinside">Xexpr.v1</span></a>? <a href="part_four.html#%28counter._%28exercise._ex~3axml-represent%29%29" class="ex-end" data-pltdoc="x"></a></div></p><p><div class="SIntrapara"><a name="(counter._(exercise._ex~3axml-interpret))"></a><span style="font-weight: bold">Exercise</span> 365. Interpret the following elements of
|
||
|
<a href="part_four.html#%28tech._xexpr..v2%29" class="techoutside" data-pltdoc="x"><span class="techinside">Xexpr.v2</span></a> as XML data:
|
||
|
</div><div class="SIntrapara"><ol><li><p><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">server</span><span class="stt"> </span><span class="RktVal">(</span><span class="RktVal">(</span><span class="RktVal">name</span><span class="stt"> </span><span class="RktVal">"example.org"</span><span class="RktVal">)</span><span class="RktVal">)</span><span class="RktVal">)</span></p></li><li><p><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">carcas</span><span class="stt"> </span><span class="RktVal">(</span><span class="RktVal">board</span><span class="stt"> </span><span class="RktVal">(</span><span class="RktVal">grass</span><span class="RktVal">)</span><span class="RktVal">)</span><span class="stt"> </span><span class="RktVal">(</span><span class="RktVal">player</span><span class="stt"> </span><span class="RktVal">(</span><span class="RktVal">(</span><span class="RktVal">name</span><span class="stt"> </span><span class="RktVal">"sam"</span><span class="RktVal">)</span><span class="RktVal">)</span><span class="RktVal">)</span><span class="RktVal">)</span></p></li><li><p><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">start</span><span class="RktVal">)</span></p></li></ol></div><div class="SIntrapara">Which ones are elements of <a href="part_four.html#%28tech._xexpr..v0%29" class="techoutside" data-pltdoc="x"><span class="techinside">Xexpr.v0</span></a> or <a href="part_four.html#%28tech._xexpr..v1%29" class="techoutside" data-pltdoc="x"><span class="techinside">Xexpr.v1</span></a>? <a href="part_four.html#%28counter._%28exercise._ex~3axml-interpret%29%29" class="ex-end" data-pltdoc="x"></a></div></p><p><div class="SIntrapara">Roughly speaking, X-expressions simulate structures via lists. The
|
||
|
simulation is convenient for programmers; it asks for the least amount of
|
||
|
keyboard typing. For example, if an X-expression does not come with an
|
||
|
attribute list, it is simply omitted. This choice of data representation
|
||
|
represents a trade-off between authoring such expressions manually and
|
||
|
processing them automatically. The best way to deal with the latter
|
||
|
problem is to provide functions that make X-expressions look like
|
||
|
structures, especially functions that access the quasi-fields:
|
||
|
</div><div class="SIntrapara"><ul><li><p><span class="RktSym">xexpr-name</span>, which extracts the tag of the element representation;</p></li><li><p><span class="RktSym">xexpr-attr</span>, which extracts the list of attributes; and</p></li><li><p><span class="RktSym">xexpr-content</span>, which extracts the list of content elements.</p></li></ul></div><div class="SIntrapara">Once we have these functions, we can use lists to represent XML yet that act as
|
||
|
if they were instances of a structure type.</div></p><p><div class="SIntrapara">These functions parse S-expressions, and parsers are tricky to design. So
|
||
|
let’s design them carefully, starting with some data examples:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">a0</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">(</span><span class="RktVal">initial</span><span class="hspace"> </span><span class="RktVal">"X"</span><span class="RktVal">)</span><span class="RktVal">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">e0</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">machine</span><span class="RktVal">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">e1</span><span class="hspace"> </span><span class="RktVal">`</span><span class="RktVal">(</span><span class="RktVal">machine</span><span class="hspace"> </span><span class="RktRdr">,</span><span class="RktSym">a0</span><span class="RktVal">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">e2</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">machine</span><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">action</span><span class="RktVal">)</span><span class="RktVal">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">e3</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">machine</span><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">)</span><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">action</span><span class="RktVal">)</span><span class="RktVal">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">e4</span><span class="hspace"> </span><span class="RktVal">`</span><span class="RktVal">(</span><span class="RktVal">machine</span><span class="hspace"> </span><span class="RktRdr">,</span><span class="RktSym">a0</span><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">action</span><span class="RktVal">)</span><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">action</span><span class="RktVal">)</span><span class="
|
||
|
twice in the construction of X-expressions. The definition of <span class="RktSym">e0</span>
|
||
|
reminds us that an X-expression may not come with either attributes or
|
||
|
content. You should be able to explain why <span class="RktSym">e2</span> and <span class="RktSym">e3</span>
|
||
|
are basically equivalent.</div></p><p><div class="SIntrapara">Next we formulate a signature, a purpose statement, and a header: <a name="(idx._(gentag._529))"></a>
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_four.html#%28tech._xexpr..v2%29" class="techoutside" data-pltdoc="x"><span class="techinside">Xexpr.v2</span></a><span class="RktCmt"> -> [</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> </span><a href="part_four.html#%28tech._attribute%29" class="techoutside" data-pltdoc="x"><span class="techinside">Attribute</span></a><span class="RktCmt">]</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">retrieves the list of attributes of </span><span class="RktSym">xe</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">xexpr-attr</span><span class="hspace"> </span><span class="RktSym">xe</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">Here we focus on <span class="RktSym">xexpr-attr</span>; we leave the other two as exercises.</div></p><p><div class="SIntrapara">Making up functional examples requires a decision concerning the extraction of
|
||
|
attributes from X-expressions without any. While our chosen representation completely
|
||
|
omits missing attributes, we must supply <span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span> for the
|
||
|
structure-based representation of XML. The function therefore produces
|
||
|
<span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span> for such X-expressions:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._check-expect%29%29" class="RktStxLink" data-pltdoc="x">check-expect</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">xexpr-attr</span><span class="hspace"> </span><span class="RktSym">e0</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._check-expect%29%29" class="RktStxLink" data-pltdoc="x">check-expect</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">xexpr-attr</span><span class="hspace"> </span><span class="RktSym">e1</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">(</span><span class="RktVal">initial</span><span class="hspace"> </span><span class="RktVal">"X"</span><span class="RktVal">)</span><span class="RktVal">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._check-expect%29%29" class="RktStxLink" data-pltdoc="x">check-expect</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">xexpr-attr</span><span class="hspace"> </span><span class="RktSym">e2</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._check-expect%29%29" class="RktStxLink" data-pltdoc="x">check-expect</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">xexpr-attr</span><span class="hspace"> </span><span class="RktSym">e3</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._check-expect%29%29" class="RktStxLink" data-pltdoc="x">check-expect</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">xexpr-attr</span><span class="hspace"> </span><span class="RktSym">e4</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">(</span><span class="RktVal">initial</span><span class="hspace"> </span><span class="RktVal">"X"</span><span class="RktVal">)</span><span class="RktVal">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div></p><p><div class="SIntrapara">It is time to develop the template. Since the data definition for
|
||
|
<a href="part_four.html#%28tech._xexpr..v2%29" class="techoutside" data-pltdoc="x"><span class="techinside">Xexpr.v2</span></a> is complex, we proceed slowly, step-by-step. First, while the
|
||
|
data definition distinguishes two kinds of X-expressions, both clauses
|
||
|
describe data constructed by <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span>ing a symbol onto a
|
||
|
list. Second, what differentiates the two clauses is the rest of the list
|
||
|
and especially the optional presence of a list of attributes. Let’s
|
||
|
translate these two insights into a template:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">xexpr-attr</span><span class="hspace"> </span><span class="RktSym">xe</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._local%29%29" class="RktStxLink" data-pltdoc="x">local</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">optional-loa+content</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._rest%29%29" class="RktValLink" data-pltdoc="x">rest</a></span><span class="hspace"> </span><span class="RktSym">xe</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._empty~3f%29%29" class="RktValLink" data-pltdoc="x">empty?</a></span><span class="hspace"> </span><span class="RktSym">optional-loa+content</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._else%29%29" class="RktStxLink" data-pltdoc="x">else</a></span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="RktPn">]</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">The local definition chops off the name of the X-expression and leaves the
|
||
|
remainder of the list, which may or may not start with a list of
|
||
|
attributes. The key is that it is just a list, and the two <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span>
|
||
|
clauses indicate so. Third, this list is <span style="font-weight: bold">not</span> defined via a
|
||
|
self-reference but as the optional <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span> of some attributes onto a
|
||
|
possibly empty list of X-expressions. In other words, we still need to
|
||
|
distinguish the two usual cases and extract the usual pieces:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">xexpr-attr</span><span class="hspace"> </span><span class="RktSym">xe</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._local%29%29" class="RktStxLink" data-pltdoc="x">local</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">optional-loa+content</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._rest%29%29" class="RktValLink" data-pltdoc="x">rest</a></span><span class="hspace"> </span><span class="RktSym">xe</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._empty~3f%29%29" class="RktValLink" data-pltdoc="x">empty?</a></span><span class="hspace"> </span><span class="RktSym">optional-loa+content</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._else%29%29" class="RktStxLink" data-pltdoc="x">else</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._first%29%29" class="RktValLink" data-pltdoc="x">first</a></span><span class="hspace"> </span><span class="RktSym">optional-loa+content</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%2
|
||
|
at hand. So, we switch to the fifth step of the design recipe. Clearly,
|
||
|
there are no attributes if the given X-expression comes with nothing but a
|
||
|
name. In the second clause, the question is whether the first item on the
|
||
|
list is a list of attributes or just an <a href="part_four.html#%28tech._xexpr..v2%29" class="techoutside" data-pltdoc="x"><span class="techinside">Xexpr.v2</span></a>. Because this
|
||
|
sounds complicated, we make a wish: <a name="(idx._(gentag._530))"></a>
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">[</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> </span><a href="part_four.html#%28tech._attribute%29" class="techoutside" data-pltdoc="x"><span class="techinside">Attribute</span></a><span class="RktCmt">] or </span><a href="part_four.html#%28tech._xexpr..v2%29" class="techoutside" data-pltdoc="x"><span class="techinside">Xexpr.v2</span></a><span class="RktCmt"> -> ???</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">determines whether </span><span class="RktSym">x</span><span class="RktCmt"> is an element of [</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> </span><a href="part_four.html#%28tech._attribute%29" class="techoutside" data-pltdoc="x"><span class="techinside">Attribute</span></a><span class="RktCmt">]</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktVal">#false</span><span class="RktCmt"> otherwise</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">list-of-attributes?</span><span class="hspace"> </span><span class="RktSym">x</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">#false</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">With this function, it is straightforward to finish <span class="RktSym">xexpr-attr</span>;
|
||
|
see <a href="part_four.html#%28counter._%28figure._fig~3axexpr-attr%29%29" data-pltdoc="x">figure <span class="FigureRef">126</span></a>. If the first item is a list of
|
||
|
attributes, the function produces it; otherwise there are no attributes.</div></p><blockquote class="Figure"><blockquote class="Centerfigure"><blockquote class="FigureInside"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">xexpr-attr</span><span class="hspace"> </span><span class="RktSym">xe</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._local%29%29" class="RktStxLink" data-pltdoc="x">local</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">optional-loa+content</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._rest%29%29" class="RktValLink" data-pltdoc="x">rest</a></span><span class="hspace"> </span><span class="RktSym">xe</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._empty~3f%29%29" class="RktValLink" data-pltdoc="x">empty?</a></span><span class="hspace"> </span><span class="RktSym">optional-loa+content</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._else%29%29" class="RktStxLink" data-pltdoc="x">else</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._local%29%29" class="RktStxLink" data-pltdoc="x">local</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">loa-or-x</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-
|
||
|
manner and get this definition:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">[</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> </span><a href="part_four.html#%28tech._attribute%29" class="techoutside" data-pltdoc="x"><span class="techinside">Attribute</span></a><span class="RktCmt">] or </span><a href="part_four.html#%28tech._xexpr..v2%29" class="techoutside" data-pltdoc="x"><span class="techinside">Xexpr.v2</span></a><span class="RktCmt"> -> </span><a href="part_one.html#%28tech._boolean%29" class="techoutside" data-pltdoc="x"><span class="techinside">Boolean</span></a></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">is </span><span class="RktSym">x</span><span class="RktCmt"> a list of attributes</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">list-of-attributes?</span><span class="hspace"> </span><span class="RktSym">x</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._empty~3f%29%29" class="RktValLink" data-pltdoc="x">empty?</a></span><span class="hspace"> </span><span class="RktSym">x</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">#true</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._else%29%29" class="RktStxLink" data-pltdoc="x">else</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._local%29%29" class="RktStxLink" data-pltdoc="x">local</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">possible-attribute</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._first%29%29" class="RktValLink" data-pltdoc="x">first</a></span><span class="hspace"> </span><span class="RktSym">x</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda
|
||
|
unremarkable. What is <span style="font-weight: bold">remarkable</span> is the signature of this
|
||
|
function. Instead of specifying a single data definition as
|
||
|
possible inputs, the signature combines two data definitions separated
|
||
|
by the English word “or.” In ISL+ such an informal signature with a
|
||
|
definite meaning is acceptable on occasion.</div></p><p><a name="(counter._(exercise._ex~3axml-accessors))"></a><span style="font-weight: bold">Exercise</span> 366. Design <span class="RktSym">xexpr-name</span> and
|
||
|
<span class="RktSym">xexpr-content</span>. <a href="part_four.html#%28counter._%28exercise._ex~3axml-accessors%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._(exercise._ex~3axml-odd-recursion))"></a><span style="font-weight: bold">Exercise</span> 367. The design recipe calls for a
|
||
|
self-reference in the template for <span class="RktSym">xexpr-attr</span>. Add this
|
||
|
self-reference to the template and then explain why the finished parsing
|
||
|
function does not contain it. <a href="part_four.html#%28counter._%28exercise._ex~3axml-odd-recursion%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._(exercise._ex~3axml-dd))"></a><span style="font-weight: bold">Exercise</span> 368. Formulate a data definition that replaces the
|
||
|
informal “or” signature for the definition of the
|
||
|
<span class="RktSym">list-of-attributes?</span> function. <a href="part_four.html#%28counter._%28exercise._ex~3axml-dd%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._(exercise._ex~3alookup-attribute))"></a><span style="font-weight: bold">Exercise</span> 369. Design <span class="RktSym">find-attr</span>. The
|
||
|
function consumes a list of attributes and a symbol. If the attributes
|
||
|
list associates the symbol with a string, the function retrieves this
|
||
|
string; otherwise it returns <span class="RktVal">#false</span>. Look up
|
||
|
<span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._assq%29%29" class="RktValLink" data-pltdoc="x">assq</a></span> and use it to define the function. <a href="part_four.html#%28counter._%28exercise._ex~3alookup-attribute%29%29" class="ex-end" data-pltdoc="x"></a></p><p>For the remainder of this chapter, <a name="(tech._xexpr)"></a><span style="font-style: italic">Xexpr</span> refers to
|
||
|
<a href="part_four.html#%28tech._xexpr..v2%29" class="techoutside" data-pltdoc="x"><span class="techinside">Xexpr.v2</span></a>. Also, we assume <span class="RktSym">xexpr-name</span>, <span class="RktSym">xexpr-attr</span>,
|
||
|
and <span class="RktSym">xexpr-content</span> are defined. Finally, we use <span class="RktSym">find-attr</span>
|
||
|
from <a href="part_four.html#%28counter._%28exercise._ex~3alookup-attribute%29%29" data-pltdoc="x">exercise 369</a> to retrieve attribute values.</p><h4>22.2<tt> </tt><a name="(part._sec~3aenum)"></a>Rendering XML Enumerations</h4><p>XML is actually a <span style="font-weight: bold">family</span> of languages. People define dialects for specific
|
||
|
channels of communication. For example, XHTML is the language for sending
|
||
|
web content in XML format. In this section, we illustrate how to design a
|
||
|
rendering function for a small snippet of XHTML, specifically the
|
||
|
enumerations from the beginning of this chapter.</p><p>The <span class="stt">ul</span> tag surrounds a so-called unordered HTML list. Each item of
|
||
|
this list is tagged with <span class="stt">li</span>, which tends to contain words but also
|
||
|
other elements, even enumerations. What “unordered HTML” means is that
|
||
|
each item is to be rendered with a leading bullet instead of a number.</p><p><div class="SIntrapara">Since <a href="part_four.html#%28tech._xexpr%29" class="techoutside" data-pltdoc="x"><span class="techinside">Xexpr</span></a> does not come with plain strings, it is not immediately
|
||
|
obvious how to represent XHTML enumerations in a subset. One option is to
|
||
|
refine the data representation one more time, so that an <a href="part_four.html#%28tech._xexpr%29" class="techoutside" data-pltdoc="x"><span class="techinside">Xexpr</span></a>
|
||
|
could be a <a href="part_one.html#%28tech._string%29" class="techoutside" data-pltdoc="x"><span class="techinside">String</span></a>. Another option is to introduce a representation
|
||
|
for text:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">An </span><a name="(tech._xword)"></a><span style="font-style: italic">XWord</span><span class="RktCmt"> is </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">word</span><span class="stt"> </span><span class="RktVal">(</span><span class="RktVal">(</span><span class="RktVal">text</span><span class="stt"> </span><a href="part_one.html#%28tech._string%29" class="techoutside" data-pltdoc="x"><span class="techinside">String</span></a><span class="RktVal">)</span><span class="RktVal">)</span><span class="RktVal">)</span><span class="RktCmt">.</span></p></blockquote></div><div class="SIntrapara">Here, we use this second option; Racket, the language from which the
|
||
|
teaching languages are derived, offers teachpacks that include
|
||
|
<a href="part_one.html#%28tech._string%29" class="techoutside" data-pltdoc="x"><span class="techinside">String</span></a> in <a href="part_four.html#%28tech._xexpr%29" class="techoutside" data-pltdoc="x"><span class="techinside">Xexpr</span></a>.</div></p><p><a name="(counter._(exercise._ex~3axml-words))"></a><span style="font-weight: bold">Exercise</span> 370. Make up three examples for <a href="part_four.html#%28tech._xword%29" class="techoutside" data-pltdoc="x"><span class="techinside">XWord</span></a>s. Design
|
||
|
<span class="RktSym">word?</span>, which checks whether some ISL+ value is in
|
||
|
<a href="part_four.html#%28tech._xword%29" class="techoutside" data-pltdoc="x"><span class="techinside">XWord</span></a>, and <span class="RktSym">word-text</span>, which extracts the value of the only
|
||
|
attribute of an instance of <a href="part_four.html#%28tech._xword%29" class="techoutside" data-pltdoc="x"><span class="techinside">XWord</span></a>. <a href="part_four.html#%28counter._%28exercise._ex~3axml-words%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._(exercise._ex~3axml+string))"></a><span style="font-weight: bold">Exercise</span> 371. Refine the definition of <a href="part_four.html#%28tech._xexpr%29" class="techoutside" data-pltdoc="x"><span class="techinside">Xexpr</span></a> so that
|
||
|
you can represent XML elements, including items in enumerations, that are plain
|
||
|
strings. <a href="part_four.html#%28counter._%28exercise._ex~3axml%2Bstring%29%29" class="ex-end" data-pltdoc="x"></a></p><p><div class="SIntrapara">Given the representation of words, representing an XHTML-style enumeration
|
||
|
of words is straightforward:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">An </span><a name="(tech._xenum..v1)"></a><span style="font-style: italic">XEnum.v1</span><span class="RktCmt"> is one of: </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">–</span><span class="RktCmt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="stt"> </span><span class="RktVal">'</span><span class="RktVal">ul</span><span class="stt"> </span><span class="RktPn">[</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="stt"> </span><a href="part_four.html#%28tech._xitem..v1%29" class="techoutside" data-pltdoc="x"><span class="techinside">XItem.v1</span></a><span class="RktPn">]</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">–</span><span class="RktCmt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="stt"> </span><span class="RktVal">'</span><span class="RktVal">ul</span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="stt"> </span><span class="RktSym">Attributes</span><span class="stt"> </span><span class="RktPn">[</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="stt"> </span><a href="part_four.html#%28tech._xitem..v1%29" class="techoutside" data-pltdoc="x"><span class="techinside">XItem.v1</span></a><span class="RktPn">]</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">An </span><a name="(tech._xitem..v1)"></a><span style="font-style: italic">XItem.v1</span><span class="RktCmt"> is one of:</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">–</span><span class="RktCmt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="stt"> </span><span class="RktVal">'</span><span class="RktVal">li</span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="stt"> </span><a href="part_four.html#%28tech._xword%29" class="techoutside" data-pltdoc="x"><span class="techinside">XWord</span></a><span class="stt"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">–</span><span class="RktCmt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/in
|
||
|
though they do not affect rendering.</div></p><p>Stop! Argue that every element of <a href="part_four.html#%28tech._xenum..v1%29" class="techoutside" data-pltdoc="x"><span class="techinside">XEnum.v1</span></a> is also in <a href="part_four.html#%28tech._xexpr%29" class="techoutside" data-pltdoc="x"><span class="techinside">XExpr</span></a>.</p><p><div class="SIntrapara">Here is a sample element of <a href="part_four.html#%28tech._xenum..v1%29" class="techoutside" data-pltdoc="x"><span class="techinside">XEnum.v1</span></a>:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">e0</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">ul</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">li</span><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">word</span><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">(</span><span class="RktVal">text</span><span class="hspace"> </span><span class="RktVal">"one"</span><span class="RktVal">)</span><span class="RktVal">)</span><span class="RktVal">)</span><span class="RktVal">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">li</span><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">word</span><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">(</span><span class="RktVal">text</span><span class="hspace"> </span><span class="RktVal">"two"</span><span class="RktVal">)</span><span class="RktVal">)</span><span class="RktVal">)</span><span class="RktVal">)</span><span class="RktVal">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">It corresponds to the inner enumeration of the example from the beginning
|
||
|
of the chapter. Rendering it with help from <span class="sroman">the <span class="Smaller"><span style="font-style: italic">2htdp/image</span></span> teachpack</span> should yield an image
|
||
|
like this:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCentered"><p><img style="vertical-align: -3.2265625px; margin: -3px -3px -3px -3px;" src="pict_146.png" alt="image" width="37.0654296875" height="38.15625"/></p></blockquote></div><div class="SIntrapara">The radius of the bullet and the distance between the bullet and the text
|
||
|
are matters of aesthetics; here the idea matters.</div></p><p><div class="SIntrapara">To create this kind of image, you might use this ISL+
|
||
|
program:<span class="refelem"><span class="refcolumn"><span class="refcontent">We developed these expressions in the interactions
|
||
|
area. What would <span style="font-style: italic">you</span> do?</span></span></span>
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">e0-rendered</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/teachpack/2htdpimage.html#%28def._%28%28lib._2htdp%2Fimage..rkt%29._above%2Falign%29%29" class="RktValLink" data-pltdoc="x">above/align</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">left</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/teachpack/2htdpimage.html#%28def._%28%28lib._2htdp%2Fimage..rkt%29._beside%2Falign%29%29" class="RktValLink" data-pltdoc="x">beside/align</a></span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">center</span><span class="hspace"> </span><span class="RktSym">BT</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/teachpack/2htdpimage.html#%28def._%28%28lib._2htdp%2Fimage..rkt%29._text%29%29" class="RktValLink" data-pltdoc="x">text</a></span><span class="hspace"> </span><span class="RktVal">"one"</span><span class="hspace"> </span><span class="RktVal">12</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">black</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/teachpack/2htdpimage.html#%28def._%28%28lib._2htdp%2Fimage..rkt%29._beside%2Falign%29%29" class="RktValLink" data-pltdoc="x">beside/align</a></span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">center</span><span class="hspace"> </span><span class="RktSym">BT</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/teachpack/2htdpimage.html#%28def._%28%28lib._2htdp%2Fimage..rkt%29._text%29%29" class="RktValLink" data-pltdoc="x">text</a></span><span class="hspace"> </span><span class="RktVal">"two"</span><span class="hspace"> </span><span class="RktVal">12</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">black</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">assuming <span class="RktSym">BT</span> is a rendering of a bullet.</div></p><p>Now let’s design the function carefully. Since the data representation
|
||
|
requires two data definitions, the design recipe tells you that you must
|
||
|
design two functions in parallel. A second look reveals, however, that in
|
||
|
this particular case the second data definition is disconnected from the
|
||
|
first one, meaning we can deal with it separately.</p><p><div class="SIntrapara">Furthermore, the definition for <a href="part_four.html#%28tech._xitem..v1%29" class="techoutside" data-pltdoc="x"><span class="techinside">XItem.v1</span></a> consists of two
|
||
|
clauses, meaning the function itself should consist of a <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span>
|
||
|
with two clauses. The point of viewing <a href="part_four.html#%28tech._xitem..v1%29" class="techoutside" data-pltdoc="x"><span class="techinside">XItem.v1</span></a> as a sub-language
|
||
|
of <a href="part_four.html#%28tech._xexpr%29" class="techoutside" data-pltdoc="x"><span class="techinside">Xexpr</span></a>, however, is to think of these two clauses in terms of
|
||
|
<a href="part_four.html#%28tech._xexpr%29" class="techoutside" data-pltdoc="x"><span class="techinside">Xexpr</span></a> selector functions, in particular,
|
||
|
<span class="RktSym">xexpr-content</span>. With this function we can extract the textual part
|
||
|
of an item, regardless of whether it comes with attributes or not: <a name="(idx._(gentag._531))"></a>
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_four.html#%28tech._xitem..v1%29" class="techoutside" data-pltdoc="x"><span class="techinside">XItem.v1</span></a><span class="RktCmt"> -> </span><a href="part_one.html#%28tech._image%29" class="techoutside" data-pltdoc="x"><span class="techinside">Image</span></a><span class="RktCmt"> </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">renders an item as a "word" prefixed by a bullet </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">render-item1</span><span class="hspace"> </span><span class="RktSym">i</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">xexpr-content</span><span class="hspace"> </span><span class="RktSym">i</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">In general, <span class="RktSym">xexpr-content</span> extracts a list of <a href="part_four.html#%28tech._xexpr%29" class="techoutside" data-pltdoc="x"><span class="techinside">Xexpr</span></a>;
|
||
|
in this specific case, the list contains exactly one <a href="part_four.html#%28tech._xword%29" class="techoutside" data-pltdoc="x"><span class="techinside">XWord</span></a>,
|
||
|
and this word contains one text:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">render-item1</span><span class="hspace"> </span><span class="RktSym">i</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._local%29%29" class="RktStxLink" data-pltdoc="x">local</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">content</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">xexpr-content</span><span class="hspace"> </span><span class="RktSym">i</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">element</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._first%29%29" class="RktValLink" data-pltdoc="x">first</a></span><span class="hspace"> </span><span class="RktSym">content</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">a-word</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">word-text</span><span class="hspace"> </span><span class="RktSym">element</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="hspace"> </span><span class="RktSym">a-word</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">From here, it is straightforward:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">render-item1</span><span class="hspace"> </span><span class="RktSym">i</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._local%29%29" class="RktStxLink" data-pltdoc="x">local</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">content</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">xexpr-content</span><span class="hspace"> </span><span class="RktSym">i</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">element</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._first%29%29" class="RktValLink" data-pltdoc="x">first</a></span><span class="hspace"> </span><span class="RktSym">content</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">a-word</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">word-text</span><span class="hspace"> </span><span class="RktSym">element</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">item</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/teachpack/2htdpimage.html#%28def._%28%28lib._2htdp%2Fimage..rkt%29._text%29%29" class="RktValLink" data-pltdoc="x">text</a></span><span class="hspace"> </span><span class="RktSym">a-word</span><span class="hspace"> </span><span class="RktVal">12</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">black</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang
|
||
|
question of rendering it as text and equipping it with a leading bullet;
|
||
|
see the examples above for how you might discover this last step.</div></p><p><a name="(counter._(exercise._ex~3axml-item1))"></a><span style="font-weight: bold">Exercise</span> 372. Before you read on, equip the definition of
|
||
|
<span class="RktSym">render-item1</span> with tests. Make sure to formulate these tests in
|
||
|
such a way that they don’t depend on the <span class="RktSym">BT</span> constant. Then explain
|
||
|
<span style="font-weight: bold">how</span> the function works; keep in mind that the purpose statement
|
||
|
explains <span style="font-weight: bold">what</span> it does. <a href="part_four.html#%28counter._%28exercise._ex~3axml-item1%29%29" class="ex-end" data-pltdoc="x"></a></p><p><div class="SIntrapara">Now we can focus on the design of a function that renders an
|
||
|
enumeration. Using the example from above, the first two design steps are
|
||
|
easy: <a name="(idx._(gentag._532))"></a>
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_four.html#%28tech._xenum..v1%29" class="techoutside" data-pltdoc="x"><span class="techinside">XEnum.v1</span></a><span class="RktCmt"> -> </span><a href="part_one.html#%28tech._image%29" class="techoutside" data-pltdoc="x"><span class="techinside">Image</span></a><span class="RktCmt"> </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">renders a simple enumeration as an image </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._check-expect%29%29" class="RktStxLink" data-pltdoc="x">check-expect</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">render-enum1</span><span class="hspace"> </span><span class="RktSym">e0</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">e0-rendered</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">render-enum1</span><span class="hspace"> </span><span class="RktSym">xe</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/teachpack/2htdpimage.html#%28def._%28%28lib._2htdp%2Fimage..rkt%29._empty-image%29%29" class="RktValLink" data-pltdoc="x">empty-image</a></span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">The key step is the development of a template. According to the data
|
||
|
definition, an element of <a href="part_four.html#%28tech._xenum..v1%29" class="techoutside" data-pltdoc="x"><span class="techinside">XEnum.v1</span></a> contains one interesting piece
|
||
|
of data, namely, the (representation of the) XML elements. The first item
|
||
|
is always <span class="RktVal">'</span><span class="RktVal">ul</span>, so there is no need to extract it, and the second,
|
||
|
optional item is a list of attributes, which we ignore. With this in mind, the
|
||
|
first template draft looks just like the one for <span class="RktSym">render-item1</span>:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">render-enum1</span><span class="hspace"> </span><span class="RktSym">xe</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">xexpr-content</span><span class="hspace"> </span><span class="RktSym">xe</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="RktPn">)</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">[</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> </span><a href="part_four.html#%28tech._xitem..v1%29" class="techoutside" data-pltdoc="x"><span class="techinside">XItem.v1</span></a><span class="RktCmt">]</span></td></tr></table></blockquote></div></p><p><div class="SIntrapara">While the <a name="(idx._(gentag._533))"></a>data-oriented design recipe tells you that you should design a separate
|
||
|
function whenever you encounter a complex form of data, the
|
||
|
abstraction-based <a name="(idx._(gentag._534))"></a>design recipe from <a href="part_three.html" data-pltdoc="x">Abstraction</a> tells you to
|
||
|
reuse an existing abstraction, say, a list-processing function from
|
||
|
<a href="part_three.html#%28counter._%28figure._fig~3aisl-ho-list%29%29" data-pltdoc="x">figures <span class="FigureRef">95</span></a> and <a href="part_three.html#%28counter._%28figure._fig~3aisl-ho-list2%29%29" data-pltdoc="x"><span class="FigureRef">96</span></a>, when possible.
|
||
|
Given that <span class="RktSym">render-enum1</span> is supposed to process a
|
||
|
list and create a single image from it, the only two list-processing
|
||
|
abstractions whose signatures fit the bill are <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._foldr%29%29" class="RktValLink" data-pltdoc="x">foldr</a></span> and
|
||
|
<span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._foldl%29%29" class="RktValLink" data-pltdoc="x">foldl</a></span>. If you also study their purpose statements, you see a
|
||
|
pattern that is like the <span class="RktSym">e0-rendered</span> example above, especially
|
||
|
for <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._foldr%29%29" class="RktValLink" data-pltdoc="x">foldr</a></span>. Let’s try to use it, following the reuse design
|
||
|
recipe:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">render-enum1</span><span class="hspace"> </span><span class="RktSym">xe</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._local%29%29" class="RktStxLink" data-pltdoc="x">local</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">content</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">xexpr-content</span><span class="hspace"> </span><span class="RktSym">xe</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_four.html#%28tech._xitem..v1%29" class="techoutside" data-pltdoc="x"><span class="techinside">XItem.v1</span></a><span class="RktCmt"> </span><a href="part_one.html#%28tech._image%29" class="techoutside" data-pltdoc="x"><span class="techinside">Image</span></a><span class="RktCmt"> -> </span><a href="part_one.html#%28tech._image%29" class="techoutside" data-pltdoc="x"><span class="techinside">Image</span></a><span class="RktCmt"> </span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">deal-with-one</span><span class="hspace"> </span><span class="RktSym">item</span><span class="hspace"> </span><span class="RktSym">so-far</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._foldr%29%29" class="RktValLink" data-pltdoc="x">foldr</a></span><span class="hspace"> </span><span class="RktSym">deal-with-one</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/teachpack/2htdpimage.html#%28def._%28%28lib._2htdp%2Fimage..rkt%29._empty-image%29%29" class="RktValLink" data-pltdoc="x">empty-image</a></span><span class="hspace"> </span><span class="RktSym">content</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">From the type matching, you also know that:
|
||
|
</div><div class="SIntrapara"><ol><li><p>the first argument to <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._foldr%29%29" class="RktValLink" data-pltdoc="x">foldr</a></span> must be a two-argument function;</p></li><li><p>the second argument must be an image; and</p></li><li><p>the last argument is the list representing XML content.</p></li></ol></div><div class="SIntrapara">Naturally <span class="RktSym"><a href="https://docs.racket-lang.org/teachpack/2htdpimage.html#%28def._%28%28lib._2htdp%2Fimage..rkt%29._empty-image%29%29" class="RktValLink" data-pltdoc="x">empty-image</a></span> is the correct starting point.</div></p><p><div class="SIntrapara">This design-by-reuse focuses our attention on the
|
||
|
function to be “folded” over the list. It turns one item and the image
|
||
|
that <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._foldr%29%29" class="RktValLink" data-pltdoc="x">foldr</a></span> has created so far into another image. The signature
|
||
|
for <span class="RktSym">deal-with-one</span> articulates this insight. Since the first
|
||
|
argument is an <a href="part_four.html#%28tech._xitem..v1%29" class="techoutside" data-pltdoc="x"><span class="techinside">XItem.v1</span></a>, <span class="RktSym">render-item1</span> is the
|
||
|
function that renders it. This yields two images that must be combined:
|
||
|
the image of the first item and the image of the rest of the
|
||
|
items. To stack them, we use <span class="RktSym"><a href="https://docs.racket-lang.org/teachpack/2htdpimage.html#%28def._%28%28lib._2htdp%2Fimage..rkt%29._above%29%29" class="RktValLink" data-pltdoc="x">above</a></span>: <a name="(idx._(gentag._535))"></a>
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">render-enum1</span><span class="hspace"> </span><span class="RktSym">xe</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._local%29%29" class="RktStxLink" data-pltdoc="x">local</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">content</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">xexpr-content</span><span class="hspace"> </span><span class="RktSym">xe</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_four.html#%28tech._xitem..v1%29" class="techoutside" data-pltdoc="x"><span class="techinside">XItem.v1</span></a><span class="RktCmt"> </span><a href="part_one.html#%28tech._image%29" class="techoutside" data-pltdoc="x"><span class="techinside">Image</span></a><span class="RktCmt"> -> </span><a href="part_one.html#%28tech._image%29" class="techoutside" data-pltdoc="x"><span class="techinside">Image</span></a><span class="RktCmt"> </span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">deal-with-one</span><span class="hspace"> </span><span class="RktSym">item</span><span class="hspace"> </span><span class="RktSym">so-far</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/teachpack/2htdpimage.html#%28def._%28%28lib._2htdp%2Fimage..rkt%29._above%2Falign%29%29" class="RktValLink" data-pltdoc="x">above/align</a></span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">left</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">render-item1</span><span class="hspace"> </span><span class="RktSym">item</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktSym">so-far</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-interm
|
||
|
the full-fledged case. In the real world, web browsers must cope with
|
||
|
arbitrarily nested enumerations that arrive over the web. In XML and its
|
||
|
web browser dialect XHTML, nesting is straightforward. Any element may
|
||
|
show up as the content of any other element. To represent
|
||
|
this<span class="refelem"><span class="refcolumn"><span class="refcontent">Are you wondering whether arbitrary nesting is the
|
||
|
correct way to think about this problem? If so, develop a data definition
|
||
|
that allows only three levels of nesting and then use it.</span></span></span> relationship in our
|
||
|
limited XHTML representation, we say that an item is either a word or
|
||
|
another enumeration. <a href="part_four.html#%28counter._%28figure._fig~3axenum%29%29" data-pltdoc="x">Figure <span class="FigureRef">127</span></a> displays the second revision
|
||
|
of the data definition. It includes a revision of the data definition for
|
||
|
enumerations so that the first definition refers to the correct form of
|
||
|
item.</p><blockquote class="Herefigure"><blockquote class="Centerfigure"><blockquote class="FigureInside"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">SIZE</span><span class="hspace"> </span><span class="RktVal">12</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">font size </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">COLOR</span><span class="hspace"> </span><span class="RktVal">"black"</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">font color </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">BT</span><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">a graphical constant </span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/teachpack/2htdpimage.html#%28def._%28%28lib._2htdp%2Fimage..rkt%29._beside%29%29" class="RktValLink" data-pltdoc="x">beside</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/teachpack/2htdpimage.html#%28def._%28%28lib._2htdp%2Fimage..rkt%29._circle%29%29" class="RktValLink" data-pltdoc="x">circle</a></span><span class="hspace"> </span><span class="RktVal">1</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">solid</span><span class="hspace"> </span><span class="RktSym">BLACK</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/teachpack/2htdpimage.html#%28def._%28%28lib._2htdp%2Fimage..rkt%29._text%29%29" class="RktValLink" data-pltdoc="x">text</a></span><span class="hspace"> </span><span class="RktVal">" "</span><span class="hspace"> </span><span class="RktSym">SIZE</span><span class="hspace"> </span><span class="RktSym">COLOR</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_one.html#%28tech._image%29" class="techoutside" data-pltdoc="x"><span class="techinside">Image</span></a><span class="RktCmt"> -> </span><a href="part_one.html#%28tech._image%29" class="techoutside" data-pltdoc="x"><span class="techinside">Image</span></a></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">marks item with bullet</span><span class="hspace"> </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">bulletize</span><span class="hspace"> </span><span class="RktSym">item</span><span class="RktPn
|
||
|
rendering functions. Put differently, we need to revise
|
||
|
<span class="RktSym">render-enum1</span> and <span class="RktSym">render-item1</span> so that they can cope with
|
||
|
<a href="part_four.html#%28tech._xenum..v2%29" class="techoutside" data-pltdoc="x"><span class="techinside">XEnum.v2</span></a> and <a href="part_four.html#%28tech._xitem..v2%29" class="techoutside" data-pltdoc="x"><span class="techinside">XItem.v2</span></a>, respectively. Software engineers face
|
||
|
these kinds of questions all the time, and it is another situation where
|
||
|
the <a name="(idx._(gentag._536))"></a>design recipe shines.</p><p><a href="part_four.html#%28counter._%28figure._fig~3aenum%29%29" data-pltdoc="x">Figure <span class="FigureRef">128</span></a> shows the complete answer. Since the change is
|
||
|
confined to the data definitions for <a href="part_four.html#%28tech._xitem..v2%29" class="techoutside" data-pltdoc="x"><span class="techinside">XItem.v2</span></a>, it should not come
|
||
|
as a surprise that the change to the rendering program shows up in the
|
||
|
function for rendering items. While <span class="RktSym">render-item1</span> does not need to
|
||
|
distinguish between different forms of <a href="part_four.html#%28tech._xitem..v1%29" class="techoutside" data-pltdoc="x"><span class="techinside">XItem.v1</span></a>,
|
||
|
<span class="RktSym">render-item</span> is forced to use a <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span> because
|
||
|
<a href="part_four.html#%28tech._xitem..v2%29" class="techoutside" data-pltdoc="x"><span class="techinside">XItem.v2</span></a> lists two different kinds of items. Given that this data
|
||
|
definition is close to one from the real world, the distinguishing
|
||
|
characteristic is not something simple—<wbr></wbr>like <span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span> vs
|
||
|
<span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span>—<wbr></wbr>but a specific piece of the given item. If the item’s
|
||
|
content is a <a href="part_four.html#%28tech._xword%29" class="techoutside" data-pltdoc="x"><span class="techinside">XWord</span></a>, the rendering function proceeds as before.
|
||
|
Otherwise, the item contains an enumeration, in which case
|
||
|
<span class="RktSym">render-item</span> uses <span class="RktSym">render-enum</span> to deal with the data,
|
||
|
because the data definition for <a href="part_four.html#%28tech._xitem..v2%29" class="techoutside" data-pltdoc="x"><span class="techinside">XItem.v2</span></a> refers back to
|
||
|
<a href="part_four.html#%28tech._xenum..v2%29" class="techoutside" data-pltdoc="x"><span class="techinside">XEnum.v2</span></a> precisely at this point.<a name="(idx._(gentag._537))"></a></p><p><a name="(counter._(exercise._ex~3aenum2-test))"></a><span style="font-weight: bold">Exercise</span> 373. <a href="part_four.html#%28counter._%28figure._fig~3aenum%29%29" data-pltdoc="x">Figure <span class="FigureRef">128</span></a> is missing test
|
||
|
cases. Develop test cases for all the functions. <a href="part_four.html#%28counter._%28exercise._ex~3aenum2-test%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(idx._(gentag._538))"></a> <a name="(idx._(gentag._539))"></a></p><p><a name="(counter._(exercise._ex~3aenum2-design))"></a><span style="font-weight: bold">Exercise</span> 374. The data definitions in <a href="part_four.html#%28counter._%28figure._fig~3axenum%29%29" data-pltdoc="x">figure <span class="FigureRef">127</span></a>
|
||
|
use <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span>. Rewrite them so they use <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span>. Then use the
|
||
|
recipe to design the rendering functions for <a href="part_four.html#%28tech._xenum..v2%29" class="techoutside" data-pltdoc="x"><span class="techinside">XEnum.v2</span></a> and
|
||
|
<a href="part_four.html#%28tech._xitem..v2%29" class="techoutside" data-pltdoc="x"><span class="techinside">XItem.v2</span></a> from scratch. You should come up with the same definitions
|
||
|
as in <a href="part_four.html#%28counter._%28figure._fig~3aenum%29%29" data-pltdoc="x">figure <span class="FigureRef">128</span></a>. <a href="part_four.html#%28counter._%28exercise._ex~3aenum2-design%29%29" class="ex-end" data-pltdoc="x"></a></p><p><div class="SIntrapara"><a name="(counter._(exercise._ex~3aenum-refactor))"></a><span style="font-weight: bold">Exercise</span> 375. The wrapping of <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span> with
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/teachpack/2htdpimage.html#%28def._%28%28lib._2htdp%2Fimage..rkt%29._beside%2Falign%29%29" class="RktValLink" data-pltdoc="x">beside/align</a></span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">center</span><span class="hspace"> </span><span class="RktSym">BT</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="RktPn">)</span></p></blockquote></div><div class="SIntrapara"> may surprise you. Edit the
|
||
|
function definition so that the wrap-around appears once in each clause.
|
||
|
Why are you confident that your change works? Which version do you prefer? <a href="part_four.html#%28counter._%28exercise._ex~3aenum-refactor%29%29" class="ex-end" data-pltdoc="x"></a></div></p><p><a name="(counter._(exercise._ex~3aenum-count))"></a><span style="font-weight: bold">Exercise</span> 376. Design a program that counts all
|
||
|
<span class="RktVal">"hello"</span>s in an instance of <a href="part_four.html#%28tech._xenum..v2%29" class="techoutside" data-pltdoc="x"><span class="techinside">XEnum.v2</span></a>. <a href="part_four.html#%28counter._%28exercise._ex~3aenum-count%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._(exercise._ex~3aenum-subst))"></a><span style="font-weight: bold">Exercise</span> 377. Design a program that replaces
|
||
|
all <span class="RktVal">"hello"</span>s with <span class="RktVal">"bye"</span> in an enumeration. <a href="part_four.html#%28counter._%28exercise._ex~3aenum-subst%29%29" class="ex-end" data-pltdoc="x"></a></p><h4>22.3<tt> </tt><a name="(part._sec~3aconfig)"></a>Domain-Specific Languages</h4><p>Engineers routinely build large software systems that require a
|
||
|
configuration for specific contexts before they can be run. This
|
||
|
configuration task tends to fall to <span style="font-style: italic">systems administrators</span>
|
||
|
who must deal with many different software systems. The word
|
||
|
“configuration” refers to the data that the main function needs when
|
||
|
the program is launched at the command-line or via a gesture (mouse
|
||
|
click, swipe). In a sense a configuration is just an additional
|
||
|
argument, though it is usually so complex that program designers
|
||
|
prefer to handing it over via a file.</p><p>Since software engineers cannot assume that systems administrators know
|
||
|
every programming language, they tend to devise simple, special-purpose
|
||
|
configuration languages. These special languages are also known as
|
||
|
<span style="font-style: italic">domain-specific languages</span> (DSL).<span class="refelem"><span class="refcolumn"><span class="refcontent">Because
|
||
|
configurations abstract a program over various pieces of data, Paul
|
||
|
Hudak argued in the 1990s that DSLs are the <span style="font-weight: bold">ultimate abstractions</span>,
|
||
|
that is, that they generalize the ideas of <a href="part_three.html" data-pltdoc="x">Abstraction</a> to
|
||
|
perfection.</span></span></span> Developing these DSLs around a common core, say the
|
||
|
well-known XML syntax, simplifies life for systems administrators. They can
|
||
|
write small XML “programs” and thus configure the systems they must
|
||
|
launch.</p><p>While the construction of a DSL is often considered a task for an advanced
|
||
|
programmer, you are actually in a position already to understand, appreciate, and
|
||
|
implement a reasonably complex DSL. This section explains how it
|
||
|
all works. It first reacquaints you with finite state machines
|
||
|
(FSMs). Then it shows how to design, implement, and program a DSL
|
||
|
for configuring a system that simulates arbitrary FSMs.</p><p><span style="font-weight: bold">Finite State Machines Remembered</span> The theme of finite state machines
|
||
|
is an important one in computing, and this book has presented it several
|
||
|
times. Here we reuse the example from <a href="part_two.html#%28part._sec~3asec-fsm-list%29" data-pltdoc="x">Finite State Machines</a> as
|
||
|
the component for which we wish to design and implement a configuration
|
||
|
DSL.</p><blockquote class="Figure"><blockquote class="Centerfigure"><blockquote class="FigureInside"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">An </span><span style="font-style: italic">FSM</span><span class="RktCmt"> is a [</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> </span><a href="part_four.html#%28tech._1transition%29" class="techoutside" data-pltdoc="x"><span class="techinside">1Transition</span></a><span class="RktCmt">]</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">A </span><a name="(tech._1transition)"></a><span style="font-style: italic">1Transition</span><span class="RktCmt"> is a list of two items:</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="stt"> </span><a href="part_two.html#%28tech._fsm._state%29" class="techoutside" data-pltdoc="x"><span class="techinside">FSM-State</span></a><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="stt"> </span><a href="part_two.html#%28tech._fsm._state%29" class="techoutside" data-pltdoc="x"><span class="techinside">FSM-State</span></a><span class="stt"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">An </span><span style="font-style: italic">FSM-State</span><span class="RktCmt"> is a </span><a href="part_one.html#%28tech._string%29" class="techoutside" data-pltdoc="x"><span class="techinside">String</span></a><span class="RktCmt"> that specifies a color</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">data examples </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">fsm-traffic</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">(</span><span class="RktVal">"red"</span><span class="hspace"> </span><span class="RktVal">"green"</span><span class="RktVal">)</span><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">"green"</span><span class="hspace"> </span><span class="RktVal">"yellow"</span><span class="RktVal">)</span><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">"yellow"</span><span class="hspace"> </span><span class="RktVal">"red"</span><span class="RktVal">)</span><span class="RktVal">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_two.html#%28tech._fsm._state%29" class="techoutside" data-pltdoc="x"><span class="techinside">FSM-State</span></a><span class="RktCmt"> </span><a href="part_two.html#%28tech._fsm%29" class="techoutside" data-pltdoc="x"><span class="techinside">FSM</span></a><span class="RktC
|
||
|
though reformulated using just lists and using the full power of ISL+.
|
||
|
The program consists of two data definitions, one data example, and two
|
||
|
function definitions: <span class="RktSym">simulate</span> and <span class="RktSym">find</span>. Unlike the
|
||
|
related programs in preceding chapters, this one represents a transition
|
||
|
as a list of two items: the current state and the next one. <a name="(idx._(gentag._540))"></a> <a name="(idx._(gentag._541))"></a></p><p>The main function, <span class="RktSym">simulate</span>, consumes a transition table and an
|
||
|
initial state; it then evaluates a <span class="RktSym"><a href="https://docs.racket-lang.org/teachpack/2htdpuniverse.html#%28form._world._%28%28lib._2htdp%2Funiverse..rkt%29._big-bang%29%29" class="RktStxLink" data-pltdoc="x">big-bang</a></span> expression, which
|
||
|
reacts to each key event with a state transition. The states are displayed
|
||
|
as colored squares. The <span class="RktSym"><a href="https://docs.racket-lang.org/teachpack/2htdpuniverse.html#%28form._world._%28%28lib._2htdp%2Funiverse..rkt%29._to-draw%29%29" class="RktStxLink" data-pltdoc="x">to-draw</a></span> and <span class="RktSym"><a href="https://docs.racket-lang.org/teachpack/2htdpuniverse.html#%28form._world._%28%28lib._2htdp%2Funiverse..rkt%29._on-key%29%29" class="RktStxLink" data-pltdoc="x">on-key</a></span> clauses are
|
||
|
specified with <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._lambda%29%29" class="RktStxLink" data-pltdoc="x">lambda</a></span> expressions that consume the current state,
|
||
|
plus the actual key event, and that produce an image or the next state,
|
||
|
respectively.</p><p>As its signature shows, the auxiliary <span class="RktSym">find</span> function is completely
|
||
|
independent of the FSM application. It consumes a list of two-item lists
|
||
|
and an item, but the actual nature of the items is specified via
|
||
|
parameters. In the context of this program, <span class="RktCmt">X</span> and <span class="RktCmt">Y</span>
|
||
|
represent <a href="part_two.html#%28tech._fsm._state%29" class="techoutside" data-pltdoc="x"><span class="techinside">FSM-State</span></a>s, meaning <span class="RktSym">find</span> consumes a transition
|
||
|
table together with a state and produces a state. The function body uses
|
||
|
the built-in <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._assoc%29%29" class="RktValLink" data-pltdoc="x">assoc</a></span> function to perform most of the work. Look up
|
||
|
the documentation for <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._assoc%29%29" class="RktValLink" data-pltdoc="x">assoc</a></span> so that you understand why the body
|
||
|
of <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._local%29%29" class="RktStxLink" data-pltdoc="x">local</a></span> uses an <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._if%29%29" class="RktStxLink" data-pltdoc="x">if</a></span> expression.</p><p><a name="(counter._(exercise._ex~3afsm-reacquaint1))"></a><span style="font-weight: bold">Exercise</span> 378. Modify the rendering function so that it
|
||
|
overlays the name of the state onto the colored square. <a href="part_four.html#%28counter._%28exercise._ex~3afsm-reacquaint1%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._(exercise._ex~3afsm-reacquaint2))"></a><span style="font-weight: bold">Exercise</span> 379. Formulate test cases for <span class="RktSym">find</span>. <a href="part_four.html#%28counter._%28exercise._ex~3afsm-reacquaint2%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._(exercise._ex~3afsm-reacquaint3))"></a><span style="font-weight: bold">Exercise</span> 380. Reformulate the data definition for
|
||
|
<a href="part_four.html#%28tech._1transition%29" class="techoutside" data-pltdoc="x"><span class="techinside">1Transition</span></a> so that it is possible to restrict transitions to
|
||
|
certain keystrokes. Try to formulate the change so that <span class="RktSym">find</span>
|
||
|
continues to work without change. What else do you need to change to get
|
||
|
the complete program to work? Which part of the design recipe provides the
|
||
|
answer(s)? See <a href="part_two.html#%28counter._%28exercise._ex~3afsm-design3%29%29" data-pltdoc="x">exercise 229</a> for the original exercise
|
||
|
statement. <a href="part_four.html#%28counter._%28exercise._ex~3afsm-reacquaint3%29%29" class="ex-end" data-pltdoc="x"></a></p><p><span style="font-weight: bold">Configurations</span> The FSM simulation function uses two arguments,
|
||
|
which jointly describe a machine. Rather than teach a potential
|
||
|
“customer” how to open an ISL+ program in DrRacket and launch a function
|
||
|
of two arguments, the “seller” of <span class="RktSym">simulate</span> may wish to
|
||
|
supplement this product with a configuration component.</p><p><div class="SIntrapara">A configuration component consists of two parts. The first one is a widely
|
||
|
used simple language that customers use to formulate the initial arguments
|
||
|
for a component’s main function(s). The second one is a function that
|
||
|
translates what customers say into a function call for the main
|
||
|
function. For the FSM simulator, we must agree on how we represent finite
|
||
|
state machines in XML. By judicious planning, <a href="part_four.html#%28part._sec~3axml%29" data-pltdoc="x">XML as S-expressions</a> presents a
|
||
|
series of machine examples that look just right for the task. Recall the
|
||
|
final <span class="stt">machine</span> example in this section:
|
||
|
</div><div class="SIntrapara"><blockquote><table cellspacing="0" cellpadding="0" class="SVerbatim"><tr><td><p><span class="stt"><machine initial="red"></span></p></td></tr><tr><td><p><span class="stt"></span><span class="hspace"> </span><span class="stt"><action state="red"</span><span class="hspace"> </span><span class="stt">next="green" /></span></p></td></tr><tr><td><p><span class="stt"></span><span class="hspace"> </span><span class="stt"><action state="green"</span><span class="hspace"> </span><span class="stt">next="yellow" /></span></p></td></tr><tr><td><p><span class="stt"></span><span class="hspace"> </span><span class="stt"><action state="yellow" next="red" /></span></p></td></tr><tr><td><p><span class="stt"></machine></span></p></td></tr></table></blockquote></div><div class="SIntrapara">Compare it to the transition table <span class="RktSym">fsm-traffic</span> from
|
||
|
<a href="part_four.html#%28counter._%28figure._fig~3afsm-again%29%29" data-pltdoc="x">figure <span class="FigureRef">129</span></a>. Also recall the agreed-upon <a href="part_four.html#%28tech._xexpr%29" class="techoutside" data-pltdoc="x"><span class="techinside">Xexpr</span></a>
|
||
|
representation of this example:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">xm0</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">machine</span><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">(</span><span class="RktVal">initial</span><span class="hspace"> </span><span class="RktVal">"red"</span><span class="RktVal">)</span><span class="RktVal">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">action</span><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">(</span><span class="RktVal">state</span><span class="hspace"> </span><span class="RktVal">"red"</span><span class="RktVal">)</span><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">next</span><span class="hspace"> </span><span class="RktVal">"green"</span><span class="RktVal">)</span><span class="RktVal">)</span><span class="RktVal">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">action</span><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">(</span><span class="RktVal">state</span><span class="hspace"> </span><span class="RktVal">"green"</span><span class="RktVal">)</span><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">next</span><span class="hspace"> </span><span class="RktVal">"yellow"</span><span class="RktVal">)</span><span class="RktVal">)</span><span class="RktVal">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">action</span><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">(</span><span class="RktVal">state</span><span class="hspace"> </span><span class="RktVal">"yellow"</span><span class="RktVal">)</span><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">next</span><span class="hspace"> </span><span class="RktVal">"red"</span><span class="RktVal">)</span><span class="RktVal">)</span><span class="RktVal">)</span><span class="RktVal">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div></p><p><div class="SIntrapara">What we are still lacking is a general data definition that describes all
|
||
|
possible <a href="part_four.html#%28tech._xexpr%29" class="techoutside" data-pltdoc="x"><span class="techinside">Xexpr</span></a> representations of <a href="part_two.html#%28tech._fsm%29" class="techoutside" data-pltdoc="x"><span class="techinside">FSM</span></a>s:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">An </span><a name="(tech._xmachine)"></a><span style="font-style: italic">XMachine</span><span class="RktCmt"> is a nested list of this shape:</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="stt"> </span><span class="RktVal">'</span><span class="RktVal">machine</span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="stt"> </span><span class="RktVal">`</span><span class="RktVal">(</span><span class="RktVal">(</span><span class="RktVal">initial</span><span class="stt"> </span><span class="RktRdr">,</span><a href="part_two.html#%28tech._fsm._state%29" class="techoutside" data-pltdoc="x"><span class="techinside">FSM-State</span></a><span class="RktVal">)</span><span class="RktVal">)</span><span class="hspace"> </span><span class="RktPn">[</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="stt"> </span><a href="part_four.html#%28tech._x1t%29" class="techoutside" data-pltdoc="x"><span class="techinside">X1T</span></a><span class="RktPn">]</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">An </span><a name="(tech._x1t)"></a><span style="font-style: italic">X1T</span><span class="RktCmt"> is a nested list of this shape:</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="hspace"> </span><span class="RktVal">`</span><span class="RktVal">(</span><span class="RktVal">action</span><span class="stt"> </span><span class="RktVal">(</span><span class="RktVal">(</span><span class="RktVal">state</span><span class="stt"> </span><span class="RktRdr">,</span><a href="part_two.html#%28tech._fsm._state%29" class="techoutside" data-pltdoc="x"><span class="techinside">FSM-State</span></a><span class="RktVal">)</span><span class="stt"> </span><span class="RktVal">(</span><span class="RktVal">next</span><span class="stt"> </span><span class="RktRdr">,</span><a href="part_two.html#%28tech._fsm._state%29" class="techoutside" data-pltdoc="x"><span class="techinside">FSM-State</span></a><span class="RktVal">)</span><span class="RktVal">)</span><span class="RktVal">)</span></td></tr></table></blockquote></div><div class="SIntrapara">Like <a href="part_four.html#%28tech._xenum..v2%29" class="techoutside" data-pltdoc="x"><span class="techinside">XEnum.v2</span></a>, <a href="part_four.html#%28tech._xmachine%29" class="techoutside" data-pltdoc="x"><span class="techinside">XMachine</span></a> describes a subset of all
|
||
|
<a href="part_four.html#%28tech._xexpr%29" class="techoutside" data-pltdoc="x"><span class="techinside">Xexpr</span></a>. Thus, when we design functions that process this new form of
|
||
|
data, we may continue to use the generic <a href="part_four.html#%28tech._xexpr%29" class="techoutside" data-pltdoc="x"><span class="techinside">Xexpr</span></a> functions to access
|
||
|
pieces.</div></p><p><a name="(counter._(exercise._ex~3axmachine-data0))"></a><span style="font-weight: bold">Exercise</span> 381. The definitions of <a href="part_four.html#%28tech._xmachine%29" class="techoutside" data-pltdoc="x"><span class="techinside">XMachine</span></a> and
|
||
|
<a href="part_four.html#%28tech._x1t%29" class="techoutside" data-pltdoc="x"><span class="techinside">X1T</span></a> use quote, which is highly inappropriate for novice program
|
||
|
designers. Rewrite them first to use <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span> and then <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span>. <a href="part_four.html#%28counter._%28exercise._ex~3axmachine-data0%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._(exercise._ex~3axmachine-data1))"></a><span style="font-weight: bold">Exercise</span> 382. Formulate an XML configuration for the BW machine,
|
||
|
which switches from white to black and back for every key event.
|
||
|
Translate the XML configuration into an <a href="part_four.html#%28tech._xmachine%29" class="techoutside" data-pltdoc="x"><span class="techinside">XMachine</span></a> representation. See
|
||
|
<a href="part_two.html#%28counter._%28exercise._ex~3afsm-design2%29%29" data-pltdoc="x">exercise 227</a> for an implementation of the machine as a program. <a href="part_four.html#%28counter._%28exercise._ex~3axmachine-data1%29%29" class="ex-end" data-pltdoc="x"></a></p><p><div class="SIntrapara">Before we dive into the translation part of the configuration problem,
|
||
|
let’s spell it out:
|
||
|
</div><div class="SIntrapara"><blockquote><p><span style="font-weight: bold">Sample Problem</span> Design a program that uses an <a href="part_four.html#%28tech._xmachine%29" class="techoutside" data-pltdoc="x"><span class="techinside">XMachine</span></a> configuration
|
||
|
to run <span class="RktSym">simulate</span>.</p></blockquote></div><div class="SIntrapara">While this problem is specific to our case, it is easy to imagine a
|
||
|
generalization for similar systems, and we encourage you to do so.</div></p><p><div class="SIntrapara">The problem statement suggests a complete outline: <a name="(idx._(gentag._542))"></a>
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_four.html#%28tech._xmachine%29" class="techoutside" data-pltdoc="x"><span class="techinside">XMachine</span></a><span class="RktCmt"> -> </span><a href="part_two.html#%28tech._fsm._state%29" class="techoutside" data-pltdoc="x"><span class="techinside">FSM-State</span></a></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">simulates an FSM via the given configuration </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">simulate-xmachine</span><span class="hspace"> </span><span class="RktSym">xm</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">simulate</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">Following the problem statement, our function calls <span class="RktSym">simulate</span> with
|
||
|
two to-be-determined arguments. What we need to complete the definition
|
||
|
are two pieces: an initial state and a transition table. These two pieces
|
||
|
are part of <span class="RktSym">xm</span>, and we are best off wishing for appropriate
|
||
|
functions:
|
||
|
</div><div class="SIntrapara"><ul><li><p><div class="SIntrapara"><span class="RktSym">xm-state0</span> extracts the initial state from the given
|
||
|
<a href="part_four.html#%28tech._xmachine%29" class="techoutside" data-pltdoc="x"><span class="techinside">XMachine</span></a>:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._check-expect%29%29" class="RktStxLink" data-pltdoc="x">check-expect</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">xm-state0</span><span class="hspace"> </span><span class="RktSym">xm0</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">"red"</span><span class="RktPn">)</span></p></blockquote></div></p></li><li><p><div class="SIntrapara"><span class="RktSym">xm->transitions</span> translates the embedded list of
|
||
|
<a href="part_four.html#%28tech._x1t%29" class="techoutside" data-pltdoc="x"><span class="techinside">X1T</span></a>s into a list of <a href="part_four.html#%28tech._1transition%29" class="techoutside" data-pltdoc="x"><span class="techinside">1Transition</span></a>s:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._check-expect%29%29" class="RktStxLink" data-pltdoc="x">check-expect</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">xm->transitions</span><span class="hspace"> </span><span class="RktSym">xm0</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">fsm-traffic</span><span class="RktPn">)</span></p></blockquote></div></p></li></ul></div></p><p><div class="SIntrapara"><a name="(idx._(gentag._543))"></a>
|
||
|
<a name="(idx._(gentag._544))"></a>
|
||
|
<a name="(idx._(gentag._545))"></a>
|
||
|
</div><div class="SIntrapara"><blockquote class="Figure"><blockquote class="Centerfigure"><blockquote class="FigureInside"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_four.html#%28tech._xmachine%29" class="techoutside" data-pltdoc="x"><span class="techinside">XMachine</span></a><span class="RktCmt"> -> </span><a href="part_two.html#%28tech._fsm._state%29" class="techoutside" data-pltdoc="x"><span class="techinside">FSM-State</span></a><span class="RktCmt"> </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">interprets the given configuration as a state machine </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">simulate-xmachine</span><span class="hspace"> </span><span class="RktSym">xm</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">simulate</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">xm-state0</span><span class="hspace"> </span><span class="RktSym">xm</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">xm->transitions</span><span class="hspace"> </span><span class="RktSym">xm</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_four.html#%28tech._xmachine%29" class="techoutside" data-pltdoc="x"><span class="techinside">XMachine</span></a><span class="RktCmt"> -> </span><a href="part_two.html#%28tech._fsm._state%29" class="techoutside" data-pltdoc="x"><span class="techinside">FSM-State</span></a><span class="RktCmt"> </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">extracts and translates the transition table from </span><span class="RktSym">xm0</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._check-expect%29%29" class="RktStxLink" data-pltdoc="x">check-expect</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">xm-state0</span><span class="hspace"> </span><span class="RktSym">xm0</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">"red"</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">xm-state0</span><span class="hspace"> </span><span class="RktSym">xm0</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">find-attr</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">xexpr-attr</span><span class="hspace"> </span><span class="RktSym">xm0</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">initial</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktCmt">;</spa
|
||
|
<span class="RktSym">xm-state0</span> is straightforward. Given that the initial state is
|
||
|
specified as an attribute, <span class="RktSym">xm-state0</span> extracts the list of
|
||
|
attributes using <span class="RktSym">xexpr-attr</span> and then retrieves the value of
|
||
|
the <span class="RktVal">'</span><span class="RktVal">initial</span> attribute.</p><p><div class="SIntrapara">Let’s then turn to <span class="RktSym">xm->transitions</span>, which translates the transitions
|
||
|
inside of an <span class="RktSym">XMachine</span> configuration into a transition table: <a name="(idx._(gentag._546))"></a>
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_four.html#%28tech._xmachine%29" class="techoutside" data-pltdoc="x"><span class="techinside">XMachine</span></a><span class="RktCmt"> -> [</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> </span><a href="part_four.html#%28tech._1transition%29" class="techoutside" data-pltdoc="x"><span class="techinside">1Transition</span></a><span class="RktCmt">]</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">extracts & translates the transition table from </span><span class="RktSym">xm</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">xm->transitions</span><span class="hspace"> </span><span class="RktSym">xm</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">The name of the function prescribes the signature and suggests a purpose
|
||
|
statement. Our purpose statement describes a two-step process:
|
||
|
(1) extract the <span class="RktSym">Xexpr</span> representation of the transitions and (2)
|
||
|
translate them into an instance of [<a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a> <a href="part_four.html#%28tech._1transition%29" class="techoutside" data-pltdoc="x"><span class="techinside">1Transition</span></a>].</div></p><p><div class="SIntrapara">While the extraction part obviously uses <span class="RktSym">xexpr-content</span> to get the list,
|
||
|
the translation part calls for some more analysis. If you look back to the data
|
||
|
definition of <a href="part_four.html#%28tech._xmachine%29" class="techoutside" data-pltdoc="x"><span class="techinside">XMachine</span></a>, you see that the content of the <a href="part_four.html#%28tech._xexpr%29" class="techoutside" data-pltdoc="x"><span class="techinside">Xexpr</span></a> is
|
||
|
a list of <a href="part_four.html#%28tech._x1t%29" class="techoutside" data-pltdoc="x"><span class="techinside">X1T</span></a>s. The signature tells us that the transition table is a
|
||
|
list of <a href="part_four.html#%28tech._1transition%29" class="techoutside" data-pltdoc="x"><span class="techinside">1Transition</span></a>s. Indeed, it is quite obvious that each item in the
|
||
|
former list is translated into one item of the latter, which suggests a
|
||
|
use of <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._map%29%29" class="RktValLink" data-pltdoc="x">map</a></span>: <a name="(idx._(gentag._547))"></a>
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">xm->transitions</span><span class="hspace"> </span><span class="RktSym">xm</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._local%29%29" class="RktStxLink" data-pltdoc="x">local</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_four.html#%28tech._x1t%29" class="techoutside" data-pltdoc="x"><span class="techinside">X1T</span></a><span class="RktCmt"> -> </span><a href="part_four.html#%28tech._1transition%29" class="techoutside" data-pltdoc="x"><span class="techinside">1Transition</span></a></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">xaction->action</span><span class="hspace"> </span><span class="RktSym">xa</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._map%29%29" class="RktValLink" data-pltdoc="x">map</a></span><span class="hspace"> </span><span class="RktSym">xaction->action</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">xexpr-content</span><span class="hspace"> </span><span class="RktSym">xm</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">As you can see, we follow the design ideas of
|
||
|
<a href="part_three.html#%28part._sec~3ausage-examples%29" data-pltdoc="x">Using Abstractions, by Example</a> and formulate the function as a <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._local%29%29" class="RktStxLink" data-pltdoc="x">local</a></span>
|
||
|
whose body uses <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._map%29%29" class="RktValLink" data-pltdoc="x">map</a></span>. Defining <span class="RktSym">xaction->action</span> is again
|
||
|
just a matter of extracting the appropriate values from an <a href="part_four.html#%28tech._xexpr%29" class="techoutside" data-pltdoc="x"><span class="techinside">Xexpr</span></a>.</div></p><p><a href="part_four.html#%28counter._%28figure._fig~3adsl%29%29" data-pltdoc="x">Figure <span class="FigureRef">130</span></a> displays the complete solution. Here the translation
|
||
|
from the DSL to a proper function call is as large as the original
|
||
|
component. This is not the case for real-world systems; the DSL component
|
||
|
tends to be a small fraction of the overall product, which is why the
|
||
|
approach is so popular.</p><p><a name="(counter._(exercise._ex~3axmachine-data2))"></a><span style="font-weight: bold">Exercise</span> 383. Run the code in <a href="part_four.html#%28counter._%28figure._fig~3adsl%29%29" data-pltdoc="x">figure <span class="FigureRef">130</span></a> with
|
||
|
the BW Machine configuration from <a href="part_four.html#%28counter._%28exercise._ex~3axmachine-data1%29%29" data-pltdoc="x">exercise 382</a>. <a href="part_four.html#%28counter._%28exercise._ex~3axmachine-data2%29%29" class="ex-end" data-pltdoc="x"></a></p><blockquote class="Herefigure"><blockquote class="Leftfigure"><blockquote class="FigureInside"><blockquote class="SubFlow"><blockquote class="Rfilebox"><p class="Rfiletitle"><span class="Rfilename"><span class="stt">machine-configuration.xml</span></span></p><blockquote class="Rfilecontent"><table cellspacing="0" cellpadding="0" class="SVerbatim"><tr><td><p><span class="hspace"> </span><span class="stt"></span></p></td></tr><tr><td><p><span class="hspace"> </span><span class="stt"><machine initial="red"></span></p></td></tr><tr><td><p><span class="hspace"> </span><span class="stt"></span><span class="hspace"> </span><span class="stt"><action state="red"</span><span class="hspace"> </span><span class="stt">next="green" /></span></p></td></tr><tr><td><p><span class="hspace"> </span><span class="stt"></span><span class="hspace"> </span><span class="stt"><action state="green"</span><span class="hspace"> </span><span class="stt">next="yellow" /></span></p></td></tr><tr><td><p><span class="hspace"> </span><span class="stt"></span><span class="hspace"> </span><span class="stt"><action state="yellow" next="red" /></span></p></td></tr><tr><td><p><span class="hspace"> </span><span class="stt"></machine></span></p></td></tr><tr><td><p><span class="hspace"> </span><span class="stt"></span></p></td></tr></table></blockquote></blockquote></blockquote></blockquote></blockquote><p class="Centertext"><span class="Legend"><span class="FigureTarget"><a name="(counter._(figure._fig~3amachine-configuration..xml))" x-target-lift="Figure"></a>Figure 131: </span>A file with a machine configuration</span></p></blockquote><h4>22.4<tt> </tt><a name="(part._sub~3areading-xml)"></a>Reading XML</h4><p><div class="SIntrapara">Systems administrators expect that sophisticated applications read
|
||
|
configuration programs<span class="refelem"><span class="refcolumn"><span class="refcontent">This section uses
|
||
|
<span class="sroman"><span class="Smaller"><span style="font-style: italic">2htdp/batch-io</span></span></span>
|
||
|
<span class="sroman"><span class="Smaller"><span style="font-style: italic">2htdp/universe</span></span></span>, and
|
||
|
<span class="sroman"><span class="Smaller"><span style="font-style: italic">2htdp/image</span></span></span> teachpacks.</span></span></span> from a file or
|
||
|
possibly from some place on the web. In ISL+ your programs can retrieve
|
||
|
(some) XML information. <a href="part_four.html#%28counter._%28figure._fig~3axexpr-tp%29%29" data-pltdoc="x">Figure <span class="FigureRef">132</span></a> shows the relevant excerpt
|
||
|
from the teachpack. For consistency, the figure uses the suffix <span class="stt">.v3</span> for
|
||
|
its XML representation, including those data definitions for which there is
|
||
|
no version 2:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">An </span><a name="(tech._xexpr..v3)"></a><span style="font-style: italic">Xexpr.v3</span><span class="RktCmt"> is one of:</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt"> </span><span class="RktCmt">–</span><span class="RktCmt"> </span><a href="i2-3.html#%28tech._symbol%29" class="techoutside" data-pltdoc="x"><span class="techinside">Symbol</span></a></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt"> </span><span class="RktCmt">–</span><span class="RktCmt"> </span><a href="part_one.html#%28tech._string%29" class="techoutside" data-pltdoc="x"><span class="techinside">String</span></a></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt"> </span><span class="RktCmt">–</span><span class="RktCmt"> </span><a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt"> </span><span class="RktCmt">–</span><span class="RktCmt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="stt"> </span><a href="i2-3.html#%28tech._symbol%29" class="techoutside" data-pltdoc="x"><span class="techinside">Symbol</span></a><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="stt"> </span><a href="part_four.html#%28tech._attribute%2A..v3%29" class="techoutside" data-pltdoc="x"><span class="techinside">Attribute*.v3</span></a><span class="stt"> </span><span class="RktPn">[</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="stt"> </span><a href="part_four.html#%28tech._xexpr..v3%29" class="techoutside" data-pltdoc="x"><span class="techinside">Xexpr.v3</span></a><span class="RktPn">]</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt"> </span><span class="RktCmt">–</span><span class="RktCmt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="stt"> </span><a href="i2-3.html#%28tech._symbol%29" class="techoutside" data-pltdoc="x"><span class="techinside">Symbol</span></a><span class="stt"> </span><span class="RktPn">[</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="stt"> </span><a href="part_four.html#%28tech._xexpr..v3%29" class="techoutside" data-pltdoc="x"><span class="techinside">Xexpr.v3</span></a><span class="RktPn">]</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">An </span><a name="(tech._attribute*..v3)"></a><span style="font-style: italic">Attribute*.v3</span><span class="RktCmt"> is a [</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techin
|
||
|
<a name="(idx._(gentag._549))"></a>
|
||
|
<a name="(idx._(gentag._550))"></a>
|
||
|
<a name="(idx._(gentag._551))"></a>
|
||
|
<a name="(idx._(gentag._552))"></a>
|
||
|
</div><div class="SIntrapara"><blockquote class="Figure"><blockquote class="Centerfigure"><blockquote class="FigureInside"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_one.html#%28tech._any%29" class="techoutside" data-pltdoc="x"><span class="techinside">Any</span></a><span class="RktCmt"> -> </span><a href="part_one.html#%28tech._boolean%29" class="techoutside" data-pltdoc="x"><span class="techinside">Boolean</span></a><span class="RktCmt"> </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">is </span><span class="RktSym">x</span><span class="RktCmt"> an </span><a href="part_four.html#%28tech._xexpr..v3%29" class="techoutside" data-pltdoc="x"><span class="techinside">Xexpr.v3</span></a></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span style="font-weight: bold">effect</span><span class="RktCmt"> displays bad piece if </span><span class="RktSym">x</span><span class="RktCmt"> is not an </span><a href="part_four.html#%28tech._xexpr..v3%29" class="techoutside" data-pltdoc="x"><span class="techinside">Xexpr.v3</span></a></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/teachpack/2htdpbatch-io.html#%28def._%28%28lib._2htdp%2Fbatch-io..rkt%29._xexpr~3f%29%29" class="RktValLink" data-pltdoc="x">xexpr?</a></span><span class="hspace"> </span><span class="RktSym">x</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_one.html#%28tech._string%29" class="techoutside" data-pltdoc="x"><span class="techinside">String</span></a><span class="RktCmt"> -> </span><a href="part_four.html#%28tech._xexpr..v3%29" class="techoutside" data-pltdoc="x"><span class="techinside">Xexpr.v3</span></a></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">produces the first XML element in file </span><span class="RktSym">f</span><span class="RktCmt"> </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/teachpack/2htdpbatch-io.html#%28def._%28%28lib._2htdp%2Fbatch-io..rkt%29._read-xexpr%29%29" class="RktValLink" data-pltdoc="x">read-xexpr</a></span><span class="hspace"> </span><span class="RktSym">f</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_one.html#%28tech._string%29" class="techoutside" data-pltdoc="x"><span class="techinside">String</span></a><span class="RktCmt"> -> </span><a href="part_one.html#%28tech._boolean%29" class="techoutside" data-pltdoc="x"><span class="techinside">Boolean</span></a><span class="RktCmt"> </span></td></tr>
|
||
|
<span class="sroman">the <span class="Smaller"><span style="font-style: italic">2htdp/batch-io</span></span> teachpack</span> is required, a program can read the element with
|
||
|
<span class="RktSym"><a href="https://docs.racket-lang.org/teachpack/2htdpbatch-io.html#%28def._%28%28lib._2htdp%2Fbatch-io..rkt%29._read-plain-xexpr%29%29" class="RktValLink" data-pltdoc="x">read-plain-xexpr</a></span>. The function retrieves the XML element in a
|
||
|
format that matches the <a href="part_four.html#%28tech._xmachine%29" class="techoutside" data-pltdoc="x"><span class="techinside">XMachine</span></a> data definition.
|
||
|
A function for retrieving XML elements from the web is also
|
||
|
available in the teachpack. Try this in DrRacket:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/teachpack/2htdpbatch-io.html#%28def._%28%28lib._2htdp%2Fbatch-io..rkt%29._read-plain-xexpr%2Fweb%29%29" class="RktValLink" data-pltdoc="x">read-plain-xexpr/web</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._string-append%29%29" class="RktValLink" data-pltdoc="x">string-append</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">"Https://Felleisen.org/"</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">"matthias/"</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">"HtDP2e/Files/machine-configuration.xml"</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">If your computer is connected to the web, this expression retrieves our
|
||
|
standard machine configuration.</div></p><p>Reading files or web pages introduces an entirely novel idea into our
|
||
|
computational model. As <a href="i1-2.html" data-pltdoc="x">Intermezzo 1: Beginning Student Language</a> explains, a BSL program is
|
||
|
evaluated in the same manner in which you evaluate variable expressions in
|
||
|
algebra. Function definitions are also treated just like in
|
||
|
algebra. Indeed, most algebra courses introduce conditional function
|
||
|
definitions, meaning <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span> does not pose any challenges
|
||
|
either. Finally, while ISL+ introduces functions as values, the
|
||
|
evaluation model remains fundamentally the same.</p><p><div class="SIntrapara">One essential property of this computational model is that no matter how
|
||
|
often you call a function <span class="RktSym">f</span> on some argument(s) <span class="RktSym">a</span><span class="stt"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span>
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktPn">(</span><span class="RktSym">f</span><span class="hspace"> </span><span class="RktSym">a</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="RktPn">)</span></p></blockquote></div><div class="SIntrapara">the answer remains the same. The introduction of <span class="RktSym"><a href="https://docs.racket-lang.org/teachpack/2htdpbatch-io.html#%28def._%28%28lib._2htdp%2Fbatch-io..rkt%29._read-file%29%29" class="RktValLink" data-pltdoc="x">read-file</a></span>,
|
||
|
<span class="RktSym"><a href="https://docs.racket-lang.org/teachpack/2htdpbatch-io.html#%28def._%28%28lib._2htdp%2Fbatch-io..rkt%29._read-xexpr%29%29" class="RktValLink" data-pltdoc="x">read-xexpr</a></span>, and their relatives destroys this property,
|
||
|
however. The problem is that files and web sites may change over time so
|
||
|
that every time a program reads files or web sites it may get a new
|
||
|
result.</div></p><p>Consider the idea of looking up the stock price of a company. Point your
|
||
|
browser to <span class="stt">google.com/finance</span> or any other such financial web site and
|
||
|
enter the name of your favorite company, say, <span class="stt">Ford</span>. In response, the
|
||
|
site will display the current price of the company’s stock and other
|
||
|
information—<wbr></wbr>for example, how much the price has changed since the last
|
||
|
time it was posted, the current time, and many other facts and ads.
|
||
|
The important point is that as you reload this page over the course of a
|
||
|
day or a week, some of the information on this web page will change.</p><p><div class="SIntrapara">An alternative to looking up such company information manually is to write
|
||
|
a small program that retrieves such information on a regular basis, say,
|
||
|
every 15 seconds. With ISL you can write a world program that performs
|
||
|
this task. You would launch it like this:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">> </span><span class="RktPn">(</span><span class="RktSym">stock-alert</span><span class="hspace"> </span><span class="RktVal">"Ford"</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">to see a world window that displays an image like the following:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCentered"><p><img style="vertical-align: -0.0px; margin: -3px -3px -3px -3px;" src="pict_147.png" alt="image" width="316.0" height="51.0"/></p></blockquote></div></p><p><div class="SIntrapara">To develop such a program requires skills beyond normal program
|
||
|
design. First, you need to investigate how the web site formats its
|
||
|
information. In the case of Google’s financial service page, an inspection
|
||
|
of the web source code shows the following pattern near the top:
|
||
|
</div><div class="SIntrapara"><blockquote class="SVInsetFlow"><table cellspacing="0" cellpadding="0"><tr><td><p><span class="Smaller"><span class="hspace"> </span><span class="stt"><meta content="17.09" itemprop="price" /></span></span></p></td></tr><tr><td><p><span class="Smaller"><span class="hspace"> </span><span class="stt"><meta content="+0.07" itemprop="priceChange" /></span></span></p></td></tr><tr><td><p><span class="Smaller"><span class="hspace"> </span><span class="stt"><meta content="0.41" itemprop="priceChangePercent" /></span></span></p></td></tr><tr><td><p><span class="Smaller"><span class="hspace"> </span><span class="stt"><meta content="2013-08-12T16:59:06Z" itemprop="quoteTime" /></span></span></p></td></tr><tr><td><p><span class="Smaller"><span class="hspace"> </span><span class="stt"><meta content="NYSE real-time data" itemprop="dataSource" /></span></span></p></td></tr></table></blockquote></div><div class="SIntrapara">If we had a function that could search an <a href="part_four.html#%28tech._xexpr..v3%29" class="techoutside" data-pltdoc="x"><span class="techinside">Xexpr.v3</span></a> and extract
|
||
|
(the representation of XML) <span class="stt">meta</span> elements with the attribute value
|
||
|
<span class="RktVal">"price"</span> and <span class="RktVal">"priceChange"</span>, the rest of
|
||
|
<span class="RktSym">stock-alert</span> would be straightforward.</div></p><p><div class="SIntrapara"><a name="(idx._(gentag._553))"></a>
|
||
|
</div><div class="SIntrapara"><blockquote class="Herefigure"><blockquote class="Centerfigure"><blockquote class="FigureInside"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">PREFIX</span><span class="hspace"> </span><span class="RktVal">"Https://www.google.com/finance?q="</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">SIZE</span><span class="hspace"> </span><span class="RktVal">22</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">font size </span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define-struct%29%29" class="RktStxLink" data-pltdoc="x">define-struct</a></span><span class="hspace"> </span><span class="RktSym">data</span><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym">price</span><span class="hspace"> </span><span class="RktSym">delta</span><span class="RktPn">]</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">A </span><a name="(tech._stockworld)"></a><span style="font-style: italic">StockWorld</span><span class="RktCmt"> is a structure: </span><span class="RktPn">(</span><span class="RktSym">make-data</span><span class="stt"> </span><a href="part_one.html#%28tech._string%29" class="techoutside" data-pltdoc="x"><span class="techinside">String</span></a><span class="stt"> </span><a href="part_one.html#%28tech._string%29" class="techoutside" data-pltdoc="x"><span class="techinside">String</span></a><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_one.html#%28tech._string%29" class="techoutside" data-pltdoc="x"><span class="techinside">String</span></a><span class="RktCmt"> -> </span><a href="part_four.html#%28tech._stockworld%29" class="techoutside" data-pltdoc="x"><span class="techinside">StockWorld</span></a></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">retrieves the stock price of </span><span class="RktSym">co</span><span class="RktCmt"> and its change every 15s</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">stock-alert</span><span class="hspace"> </span><span class="RktSym">co</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._local%29%29" class="RktStxLink" data-pltdoc="x">local</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="Rk
|
||
|
because the web service no longer delivers stock quotes.</span></span></span></p><p><a href="part_four.html#%28counter._%28figure._fig~3areal-time%29%29" data-pltdoc="x">Figure <span class="FigureRef">133</span></a> displays the core of the program. The design of
|
||
|
<span class="RktSym">get</span> is left to the exercises because its workings are all about
|
||
|
intertwined data.</p><p>As the figure shows, the main function defines two local ones: a clock-tick
|
||
|
handler and a rendering function. The <span class="RktSym"><a href="https://docs.racket-lang.org/teachpack/2htdpuniverse.html#%28form._world._%28%28lib._2htdp%2Funiverse..rkt%29._big-bang%29%29" class="RktStxLink" data-pltdoc="x">big-bang</a></span> specification
|
||
|
requests that the clock tick every 15 seconds. When the clock ticks,
|
||
|
ISL+ applies <span class="RktSym">retrieve-stock-data</span> to the current world, which it
|
||
|
ignores. Instead, the function visits the web site via
|
||
|
<span class="RktSym"><a href="https://docs.racket-lang.org/teachpack/2htdpbatch-io.html#%28def._%28%28lib._2htdp%2Fbatch-io..rkt%29._read-xexpr%2Fweb%29%29" class="RktValLink" data-pltdoc="x">read-xexpr/web</a></span> and extracts the appropriate information with
|
||
|
<span class="RktSym">get</span>. Thus, the new world is created from newly available
|
||
|
information on the web, not some local data.</p><p><a name="(counter._(exercise._ex~3aweb-data0))"></a><span style="font-weight: bold">Exercise</span> 384. <a href="part_four.html#%28counter._%28figure._fig~3areal-time%29%29" data-pltdoc="x">Figure <span class="FigureRef">133</span></a> mentions
|
||
|
<span class="RktSym"><a href="https://docs.racket-lang.org/teachpack/2htdpbatch-io.html#%28def._%28%28lib._2htdp%2Fbatch-io..rkt%29._read-xexpr%2Fweb%29%29" class="RktValLink" data-pltdoc="x">read-xexpr/web</a></span>. See
|
||
|
<a href="part_four.html#%28counter._%28figure._fig~3axexpr-tp%29%29" data-pltdoc="x">figure <span class="FigureRef">132</span></a> for its signature and purpose
|
||
|
statement and then read its documentation to determine
|
||
|
the difference to its “plain” relative.</p><p><a href="part_four.html#%28counter._%28figure._fig~3areal-time%29%29" data-pltdoc="x">Figure <span class="FigureRef">133</span></a> is also missing several important pieces, in
|
||
|
particular the interpretation of <span class="RktSym">data</span> and purpose statements for
|
||
|
all the locally defined functions. Formulate the missing pieces so that
|
||
|
you get to understand the program. <a href="part_four.html#%28counter._%28exercise._ex~3aweb-data0%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._(exercise._ex~3aweb-data1))"></a><span style="font-weight: bold">Exercise</span> 385. Look up the current stock price for your favorite
|
||
|
company at Google’s financial service page. If you don’t favor a company,
|
||
|
pick Ford. Then save the source code of the page as a file in your working
|
||
|
directory. Use <span class="RktSym"><a href="https://docs.racket-lang.org/teachpack/2htdpbatch-io.html#%28def._%28%28lib._2htdp%2Fbatch-io..rkt%29._read-xexpr%29%29" class="RktValLink" data-pltdoc="x">read-xexpr</a></span> in DrRacket to view the source as an
|
||
|
<a href="part_four.html#%28tech._xexpr..v3%29" class="techoutside" data-pltdoc="x"><span class="techinside">Xexpr.v3</span></a>. <a href="part_four.html#%28counter._%28exercise._ex~3aweb-data1%29%29" class="ex-end" data-pltdoc="x"></a></p><p><div class="SIntrapara"><a name="(counter._(exercise._ex~3aweb-data2))"></a><span style="font-weight: bold">Exercise</span> 386. Here is the <span class="RktSym">get</span> function: <a name="(idx._(gentag._554))"></a>
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_four.html#%28tech._xexpr..v3%29" class="techoutside" data-pltdoc="x"><span class="techinside">Xexpr.v3</span></a><span class="RktCmt"> </span><a href="part_one.html#%28tech._string%29" class="techoutside" data-pltdoc="x"><span class="techinside">String</span></a><span class="RktCmt"> -> </span><a href="part_one.html#%28tech._string%29" class="techoutside" data-pltdoc="x"><span class="techinside">String</span></a></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">retrieves the value of the </span><span class="RktVal">"content"</span><span class="RktMeta"></span><span class="RktCmt"> attribute </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">from a </span><span class="RktVal">'</span><span class="RktVal">meta</span><span class="RktCmt"> element that has attribute </span><span class="RktVal">"itemprop"</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">with value </span><span class="RktSym">s</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._check-expect%29%29" class="RktStxLink" data-pltdoc="x">check-expect</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">get</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">meta</span><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">(</span><span class="RktVal">content</span><span class="hspace"> </span><span class="RktVal">"+1"</span><span class="RktVal">)</span><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">itemprop</span><span class="hspace"> </span><span class="RktVal">"F"</span><span class="RktVal">)</span><span class="RktVal">)</span><span class="RktVal">)</span><span class="hspace"> </span><span class="RktVal">"F"</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">"+1"</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">get</span><span class="hspace"> </span><span class="RktSym">x</span><span class="hspace"> </span><span class="RktSym">s</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._local%29%29" class="RktStxLink" data-pltdoc="x">local</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">result</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">get-xexpr</span><span class="hspace"> </span><span class="RktSym">x</span><span class="hspace"> </span><span class="RktSym">s</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> &nbs
|
||
|
an arbitrary <a href="part_four.html#%28tech._xexpr..v3%29" class="techoutside" data-pltdoc="x"><span class="techinside">Xexpr.v3</span></a> for the desired attribute and produces
|
||
|
[<a href="part_three.html#%28tech._sim-dd._maybe%29" class="techoutside" data-pltdoc="x"><span class="techinside">Maybe</span></a> <a href="part_one.html#%28tech._string%29" class="techoutside" data-pltdoc="x"><span class="techinside">String</span></a>].</div></p><p>Formulate test cases that look for other values than <span class="RktVal">"F"</span> and that
|
||
|
force <span class="RktSym">get</span> to signal an error.</p><p>Design <span class="RktSym">get-xexpr</span>. Derive functional examples for this function
|
||
|
from those for <span class="RktSym">get</span>. Generalize these examples so that you are
|
||
|
confident <span class="RktSym">get-xexpr</span> can traverse an arbitrary
|
||
|
<a href="part_four.html#%28tech._xexpr..v3%29" class="techoutside" data-pltdoc="x"><span class="techinside">Xexpr.v3</span></a>. Finally, formulate a test that uses the web data saved in
|
||
|
<a href="part_four.html#%28counter._%28exercise._ex~3aweb-data1%29%29" data-pltdoc="x">exercise 385</a>. <a href="part_four.html#%28counter._%28exercise._ex~3aweb-data2%29%29" class="ex-end" data-pltdoc="x"></a></p><h3>23<tt> </tt><a name="(part._ch~3asimu)"></a>Simultaneous Processing</h3><p>Some functions have to consume two arguments that belong to classes with
|
||
|
nontrivial data definitions. How to design such functions depends on
|
||
|
the relationship between the arguments. First, one of the arguments may
|
||
|
have to be treated as if it were atomic. Second, it is possible that the
|
||
|
function must process the two arguments in lockstep. Finally, the function
|
||
|
may process the given data in accordance to all possible cases. This
|
||
|
chapter illustrates the three cases with examples and provides an augmented
|
||
|
design recipe. The last section discusses the equality of compound data.</p><h4>23.1<tt> </tt><a name="(part._sec~3atwo-inputs~3acase1)"></a>Processing Two Lists Simultaneously: Case 1</h4><p><div class="SIntrapara">Consider the following signature, purpose statement, and header: <a name="(idx._(gentag._555))"></a>
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">[</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> </span><a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a><span class="RktCmt">] [</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> </span><a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a><span class="RktCmt">] -> [</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> </span><a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a><span class="RktCmt">]</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">replaces the final </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span><span class="RktCmt"> in </span><span class="RktSym">front</span><span class="RktCmt"> with </span><span class="RktSym">end</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">replace-eol-with</span><span class="hspace"> </span><span class="RktSym">front</span><span class="hspace"> </span><span class="RktSym">end</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktSym">front</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">The signature says that the function consumes two lists. Let’s see how the
|
||
|
design recipe works in this case.</div></p><p><div class="SIntrapara">We start by working through examples. If the first argument is
|
||
|
<span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span>, <span class="RktSym">replace-eol-with</span> must produce the second
|
||
|
one, no matter what it is:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._check-expect%29%29" class="RktStxLink" data-pltdoc="x">check-expect</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">replace-eol-with</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">a</span><span class="hspace"> </span><span class="RktVal">b</span><span class="RktVal">)</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">a</span><span class="hspace"> </span><span class="RktVal">b</span><span class="RktVal">)</span><span class="RktPn">)</span></p></blockquote></div><div class="SIntrapara">In contrast, if the first argument is not <span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span>, the purpose
|
||
|
statement requires that we replace <span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span> at the end of
|
||
|
<span class="RktSym">front</span> with <span class="RktSym">end</span>:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._check-expect%29%29" class="RktStxLink" data-pltdoc="x">check-expect</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">replace-eol-with</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="hspace"> </span><span class="RktVal">1</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">a</span><span class="RktVal">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="hspace"> </span><span class="RktVal">1</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">a</span><span class="RktVal">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._check-expect%29%29" class="RktStxLink" data-pltdoc="x">check-expect</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">replace-eol-with</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="hspace"> </span><span class="RktVal">2</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="hspace"> </span><span class="RktVal">1</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">a</span><span class="RktVal">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="hspace"> </span><span class="RktVal">2</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-i
|
||
|
argument is a list, the function does not need to know anything about it.
|
||
|
By implication, its template should be that of a list-processing function with
|
||
|
respect to the first argument: <a name="(idx._(gentag._556))"></a>
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">replace-eol-with</span><span class="hspace"> </span><span class="RktSym">front</span><span class="hspace"> </span><span class="RktSym">end</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._empty~3f%29%29" class="RktValLink" data-pltdoc="x">empty?</a></span><span class="hspace"> </span><span class="RktSym">front</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._else%29%29" class="RktStxLink" data-pltdoc="x">else</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._first%29%29" class="RktValLink" data-pltdoc="x">first</a></span><span class="hspace"> </span><span class="RktSym">front</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">replace-eol-with</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._rest%29%29" class="RktValLink" data-pltdoc="x">rest</a></span><span class="hspace"> </span><span class="RktSym">front</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">end</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">..
|
||
|
If <span class="RktSym">front</span> is <span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span>, <span class="RktSym">replace-eol-with</span> produces
|
||
|
<span class="RktSym">end</span>. If <span class="RktSym">front</span> is not <span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span>, we must recall what
|
||
|
the template expressions compute:
|
||
|
</div><div class="SIntrapara"><ul><li><p><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._first%29%29" class="RktValLink" data-pltdoc="x">first</a></span><span class="stt"> </span><span class="RktSym">front</span><span class="RktPn">)</span> evaluates to the first item on the list, and</p></li><li><p><span class="RktPn">(</span><span class="RktSym">replace-eol-with</span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._rest%29%29" class="RktValLink" data-pltdoc="x">rest</a></span><span class="stt"> </span><span class="RktSym">front</span><span class="RktPn">)</span><span class="stt"> </span><span class="RktSym">end</span><span class="RktPn">)</span> replaces the final
|
||
|
<span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span> in <span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._rest%29%29" class="RktValLink" data-pltdoc="x">rest</a></span><span class="stt"> </span><span class="RktSym">front</span><span class="RktPn">)</span> with <span class="RktSym">end</span>.</p></li></ul></div><div class="SIntrapara">Stop! Use the <a name="(idx._(gentag._557))"></a>table method to understand what these bullets mean for the
|
||
|
running example.</div></p><p><div class="SIntrapara">From here it is a small step to the complete definition: <a name="(idx._(gentag._558))"></a>
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">replace-eol-with</span><span class="hspace"> </span><span class="RktSym">front</span><span class="hspace"> </span><span class="RktSym">end</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._empty~3f%29%29" class="RktValLink" data-pltdoc="x">empty?</a></span><span class="hspace"> </span><span class="RktSym">front</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">end</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._else%29%29" class="RktStxLink" data-pltdoc="x">else</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._first%29%29" class="RktValLink" data-pltdoc="x">first</a></span><span class="hspace"> </span><span class="RktSym">front</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">replace-eol-with</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._rest%29%29" class="RktValLink" data-pltdoc="x">rest</a></span><span class="hspace"> </span><span class="RktSym">front</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">end</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div></p><p><a name="(counter._(exercise._ex~3across))"></a><span style="font-weight: bold">Exercise</span> 387. Design <span class="RktSym">cross</span>. The function consumes a list
|
||
|
of symbols and a list of numbers and produces all possible ordered pairs of
|
||
|
symbols and numbers. That is, when given <span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">a</span><span class="stt"> </span><span class="RktVal">b</span><span class="stt"> </span><span class="RktVal">c</span><span class="RktVal">)</span> and <span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">1</span><span class="stt"> </span><span class="RktVal">2</span><span class="RktVal">)</span>, the expected result is <span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">(</span><span class="RktVal">a</span><span class="stt"> </span><span class="RktVal">1</span><span class="RktVal">)</span><span class="stt"> </span><span class="RktVal">(</span><span class="RktVal">a</span><span class="stt"> </span><span class="RktVal">2</span><span class="RktVal">)</span><span class="stt"> </span><span class="RktVal">(</span><span class="RktVal">b</span><span class="stt"> </span><span class="RktVal">1</span><span class="RktVal">)</span><span class="stt"> </span><span class="RktVal">(</span><span class="RktVal">b</span><span class="stt"> </span><span class="RktVal">2</span><span class="RktVal">)</span><span class="stt"> </span><span class="RktVal">(</span><span class="RktVal">c</span><span class="stt"> </span><span class="RktVal">1</span><span class="RktVal">)</span><span class="stt"> </span><span class="RktVal">(</span><span class="RktVal">c</span><span class="stt"> </span><span class="RktVal">2</span><span class="RktVal">)</span><span class="RktVal">)</span>. <a href="part_four.html#%28counter._%28exercise._ex~3across%29%29" class="ex-end" data-pltdoc="x"></a></p><h4>23.2<tt> </tt><a name="(part._sec~3atwo-inputs~3acase2)"></a>Processing Two Lists Simultaneously: Case 2</h4><p><a href="part_two.html#%28part._sec~3alist-produce%29" data-pltdoc="x">Functions that Produce Lists</a> presents the function <span class="RktSym">wages*</span>, which
|
||
|
computes the weekly wages of some workers given their work hours. It
|
||
|
consumes a list of numbers, which represents the hours worked per week, and
|
||
|
produces a list of numbers, which are the corresponding weekly wages. While the
|
||
|
problem assumes that all employees received the same pay rate, even a small
|
||
|
company pays its workers differentiated wages.</p><p><div class="SIntrapara">Here we look at a slightly more realistic version. The function now consumes
|
||
|
<span style="font-weight: bold">two</span> lists: the list of hours worked and the list of corresponding
|
||
|
hourly wages. We translate this revised problem into a revised header:<a name="(idx._(gentag._559))"></a>
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">[</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> </span><a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a><span class="RktCmt">] [</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> </span><a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a><span class="RktCmt">] -> [</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> </span><a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a><span class="RktCmt">]</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">multiplies the corresponding items on </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktSym">hours</span><span class="RktCmt"> and </span><span class="RktSym">wages/h</span><span class="RktCmt"> </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span style="font-weight: bold">assume</span><span class="RktCmt"> the two lists are of equal length </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">wages*.v2</span><span class="hspace"> </span><span class="RktSym">hours</span><span class="hspace"> </span><span class="RktSym">wages/h</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">Making up examples is straightforward:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._check-expect%29%29" class="RktStxLink" data-pltdoc="x">check-expect</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">wages*.v2</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._check-expect%29%29" class="RktStxLink" data-pltdoc="x">check-expect</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">wages*.v2</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">5.65</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">40</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">226.0</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._check-expect%29%29" class="RktStxLink" data-pltdoc="x">check-expect</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">wages*.v2</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">5.65</span><span class="hspace"> </span><span class="RktVal">8.75</span><span class="RktVal">)</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">40.0</span><span class="hspace"> </span><span class="RktVal">30.0</span><span class="RktVal">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">226.0</span><span class="hspace"> </span><span class="RktVal">262.5</span><span class="RktVal">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">As required, all three examples use lists of equal length.</div></p><p><div class="SIntrapara">The assumption concerning the inputs can also be exploited for the
|
||
|
development of the template. More concretely, the condition says that
|
||
|
<span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._empty~3f%29%29" class="RktValLink" data-pltdoc="x">empty?</a></span><span class="stt"> </span><span class="RktSym">hours</span><span class="RktPn">)</span> is true when <span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._empty~3f%29%29" class="RktValLink" data-pltdoc="x">empty?</a></span><span class="stt"> </span><span class="RktSym">wages/h</span><span class="RktPn">)</span> is true, and furthermore, <span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons~3f%29%29" class="RktValLink" data-pltdoc="x">cons?</a></span><span class="stt"> </span><span class="RktSym">hours</span><span class="RktPn">)</span> is true
|
||
|
when <span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons~3f%29%29" class="RktValLink" data-pltdoc="x">cons?</a></span><span class="stt"> </span><span class="RktSym">wages/h</span><span class="RktPn">)</span> is true. It is thus acceptable to
|
||
|
use a template for one of the two lists:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">wages*.v2</span><span class="hspace"> </span><span class="RktSym">hours</span><span class="hspace"> </span><span class="RktSym">wages/h</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._empty~3f%29%29" class="RktValLink" data-pltdoc="x">empty?</a></span><span class="hspace"> </span><span class="RktSym">hours</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._else%29%29" class="RktStxLink" data-pltdoc="x">else</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._first%29%29" class="RktValLink" data-pltdoc="x">first</a></span><span class="hspace"> </span><span class="RktSym">hours</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._first%29%29" class="RktValLink" data-pltdoc="x">first</a></span><span class="hspace"> </span><span class="RktSym">wages/h</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">wages*.v2</span><span class="hspace"> </span><span
|
||
|
<span class="RktSym">wages/h</span> are <span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span>. Hence no selector expressions are
|
||
|
needed. In the second clause, both <span class="RktSym">hours</span> and <span class="RktSym">wages/h</span>
|
||
|
are <span class="RktSym">constructed</span> lists, which means we need four selector
|
||
|
expressions. Finally, because the last
|
||
|
two are lists of equal length, they make up a natural candidate for the
|
||
|
natural recursion of <span class="RktSym">wages*.v2</span>.</div></p><p>The only unusual aspect of this template is that the recursive application
|
||
|
consists of two expressions, both selector expressions for the two
|
||
|
arguments. But, this idea directly follows from the assumption.</p><p><div class="SIntrapara">From here, it is a short step to a complete function definition:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">wages*.v2</span><span class="hspace"> </span><span class="RktSym">hours</span><span class="hspace"> </span><span class="RktSym">wages/h</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._empty~3f%29%29" class="RktValLink" data-pltdoc="x">empty?</a></span><span class="hspace"> </span><span class="RktSym">hours</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._else%29%29" class="RktStxLink" data-pltdoc="x">else</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">weekly-wage</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._first%29%29" class="RktValLink" data-pltdoc="x">first</a></span><span class="hspace"> </span><span class="RktSym">hours</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._first%29%29" class="RktValLink" data-pltdoc="x">first</a></span><span class="hspace"> </span><span class="RktSym">wages/h</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">wages*.v2</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._rest%29%29" class="RktValLink" data-pltdoc="x">rest</a></span><span class="hspace"> </span><span class="RktSym">hours</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._rest%29%29" class="RktValLink" data-pltdoc="x">rest</a></span><span class="hspace"> </span><span class="RktSym"
|
||
|
clause is <span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span>. In the second one, we have three values
|
||
|
available:
|
||
|
</div><div class="SIntrapara"><ol><li><p><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._first%29%29" class="RktValLink" data-pltdoc="x">first</a></span><span class="stt"> </span><span class="RktSym">hours</span><span class="RktPn">)</span>, which represents the first number
|
||
|
of weekly hours;</p></li><li><p><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._first%29%29" class="RktValLink" data-pltdoc="x">first</a></span><span class="stt"> </span><span class="RktSym">wages/h</span><span class="RktPn">)</span>, which is the first pay rate; and</p></li><li><p><span class="RktPn">(</span><span class="RktSym">wages*.v2</span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._rest%29%29" class="RktValLink" data-pltdoc="x">rest</a></span><span class="stt"> </span><span class="RktSym">hours</span><span class="RktPn">)</span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._rest%29%29" class="RktValLink" data-pltdoc="x">rest</a></span><span class="stt"> </span><span class="RktSym">wages/h</span><span class="RktPn">)</span><span class="RktPn">)</span>, which, according
|
||
|
to the purpose statement, computes the list of weekly wages for the
|
||
|
remainders of the two lists.</p></li></ol></div><div class="SIntrapara">Now we just need to combine these values to get the final answer. As
|
||
|
suggested by the examples, we must compute the weekly wage for the first
|
||
|
employee and <span class="RktSym">construct</span> a list from that wage and the rest of the
|
||
|
wages:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">weekly-wage</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._first%29%29" class="RktValLink" data-pltdoc="x">first</a></span><span class="hspace"> </span><span class="RktSym">hours</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._first%29%29" class="RktValLink" data-pltdoc="x">first</a></span><span class="hspace"> </span><span class="RktSym">wages/h</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">wages*.v2</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._rest%29%29" class="RktValLink" data-pltdoc="x">rest</a></span><span class="hspace"> </span><span class="RktSym">hours</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._rest%29%29" class="RktValLink" data-pltdoc="x">rest</a></span><span class="hspace"> </span><span class="RktSym">wages/h</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">The auxiliary function <span class="RktSym">weekly-wage</span> uses the number of hours
|
||
|
worked and the pay rate to compute the weekly wage for one worker:
|
||
|
<a name="(idx._(gentag._560))"></a>
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a><span class="RktCmt"> </span><a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a><span class="RktCmt"> -> </span><a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">computes the weekly wage from </span><span class="RktSym">pay-rate</span><span class="RktCmt"> and </span><span class="RktSym">hours</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">weekly-wage</span><span class="hspace"> </span><span class="RktSym">pay-rate</span><span class="hspace"> </span><span class="RktSym">hours</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._%2A%29%29" class="RktValLink" data-pltdoc="x">*</a></span><span class="hspace"> </span><span class="RktSym">pay-rate</span><span class="hspace"> </span><span class="RktSym">hours</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">Stop! Which function do you need to use if you wish to compute the wages
|
||
|
for one worker? Which function do you need to change if you wish to
|
||
|
deal with income taxes?</div></p><p><a name="(counter._(exercise._ex~3aweekly-wage))"></a><span style="font-weight: bold">Exercise</span> 388. In the real world, <span class="RktSym">wages*.v2</span> consumes
|
||
|
lists of employee structures and lists of work records. An employee
|
||
|
structure contains an employee’s name, social security number, and pay
|
||
|
rate. A work record also contains an employee’s name and the number of
|
||
|
hours worked in a week. The result is a list of structures that contain the
|
||
|
name of the employee and the weekly wage.</p><p>Modify the program in this section so that it works on these realistic
|
||
|
versions of data. Provide the necessary structure type definitions and data
|
||
|
definitions. Use the design recipe to guide the modification process. <a href="part_four.html#%28counter._%28exercise._ex~3aweekly-wage%29%29" class="ex-end" data-pltdoc="x"></a></p><p><div class="SIntrapara"><a name="(counter._(exercise._ex~3azip))"></a><span style="font-weight: bold">Exercise</span> 389. Design the <span class="RktSym">zip</span> function, which consumes a list
|
||
|
of names, represented as strings, and a list of phone numbers, also
|
||
|
strings. It combines those equally long lists into a list of phone records:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define-struct%29%29" class="RktStxLink" data-pltdoc="x">define-struct</a></span><span class="hspace"> </span><span class="RktSym">phone-record</span><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym">name</span><span class="hspace"> </span><span class="RktSym">number</span><span class="RktPn">]</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">A </span><a name="(tech._phonerecord)"></a><span style="font-style: italic">PhoneRecord</span><span class="RktCmt"> is a structure:</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">make-phone-record</span><span class="stt"> </span><a href="part_one.html#%28tech._string%29" class="techoutside" data-pltdoc="x"><span class="techinside">String</span></a><span class="stt"> </span><a href="part_one.html#%28tech._string%29" class="techoutside" data-pltdoc="x"><span class="techinside">String</span></a><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">Assume that the corresponding list items belong to the same person. <a href="part_four.html#%28counter._%28exercise._ex~3azip%29%29" class="ex-end" data-pltdoc="x"></a></div></p><h4>23.3<tt> </tt><a name="(part._sec~3atwo-inputs~3acase3)"></a>Processing Two Lists Simultaneously: Case 3</h4><p><div class="SIntrapara">Here is a third type of problem:
|
||
|
</div><div class="SIntrapara"><blockquote><p><span style="font-weight: bold">Sample Problem</span> Given a list of symbols <span class="RktSym">los</span> and a natural number
|
||
|
<span class="RktSym">n</span>, the function <span class="RktSym">list-pick</span> extracts the <span class="RktSym">n</span>th symbol
|
||
|
from <span class="RktSym">los</span>; if there is no such symbol, it signals an error.</p></blockquote></div><div class="SIntrapara">The question is how well the recipe works for the design of <span class="RktSym">list-pick</span>.</div></p><p><div class="SIntrapara">While the data definition for a list of symbols is fairly familiar by now,
|
||
|
recall the class of natural numbers from <a href="part_two.html#%28part._sec~3anats%29" data-pltdoc="x">Natural Numbers</a>:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span style="font-style: italic">N</span><span class="RktCmt"> is one of: </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">–</span><span class="RktCmt"> </span><span class="RktVal">0</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">–</span><span class="RktCmt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._add1%29%29" class="RktValLink" data-pltdoc="x">add1</a></span><span class="stt"> </span><a href="part_two.html#%28tech._n%29" class="techoutside" data-pltdoc="x"><span class="techinside">N</span></a><span class="RktPn">)</span></td></tr></table></blockquote></div></p><p><div class="SIntrapara">Now we can proceed to the second step: <a name="(idx._(gentag._561))"></a>
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">[</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> </span><a href="i2-3.html#%28tech._symbol%29" class="techoutside" data-pltdoc="x"><span class="techinside">Symbol</span></a><span class="RktCmt">] </span><a href="part_two.html#%28tech._n%29" class="techoutside" data-pltdoc="x"><span class="techinside">N</span></a><span class="RktCmt"> -> </span><a href="i2-3.html#%28tech._symbol%29" class="techoutside" data-pltdoc="x"><span class="techinside">Symbol</span></a></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">extracts the </span><span class="RktSym">n</span><span class="RktCmt">th symbol from </span><span class="RktSym">l</span><span class="RktCmt">; </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">signals an error if there is no such symbol</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">list-pick</span><span class="hspace"> </span><span class="RktSym">l</span><span class="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">a</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">Both lists of symbols and natural numbers are classes with complex data
|
||
|
definitions. This combination makes the problem nonstandard, meaning we
|
||
|
must pay attention to every detail for every step of the design recipe.</div></p><p><div class="SIntrapara">At this point, we usually pick some input examples and figure out what the
|
||
|
desired output is. We start with inputs for which the function has to
|
||
|
work flawlessly: <span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">a</span><span class="stt"> </span><span class="RktVal">b</span><span class="stt"> </span><span class="RktVal">c</span><span class="RktVal">)</span> and <span class="RktVal">2</span>. For a list of three
|
||
|
symbols and the index <span class="RktVal">2</span>, <span class="RktSym">list-pick</span> must return a
|
||
|
symbol. The question is whether it is <span class="RktVal">'</span><span class="RktVal">b</span> or <span class="RktVal">'</span><span class="RktVal">c</span>. In grade
|
||
|
school, you would have counted <span class="RktVal">1</span>, <span class="RktVal">2</span>, and picked
|
||
|
<span class="RktVal">'</span><span class="RktVal">b</span> without a first thought. But this is computer science, not
|
||
|
grade school. Here people start counting from <span class="RktVal">0</span>, meaning that
|
||
|
<span class="RktVal">'</span><span class="RktVal">c</span> is an equally appropriate choice. And indeed, this is the
|
||
|
choice we use:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._check-expect%29%29" class="RktStxLink" data-pltdoc="x">check-expect</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">list-pick</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">a</span><span class="hspace"> </span><span class="RktVal">b</span><span class="hspace"> </span><span class="RktVal">c</span><span class="RktVal">)</span><span class="hspace"> </span><span class="RktVal">2</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">c</span><span class="RktPn">)</span></p></blockquote></div></p><p>Now that we have eliminated this fine point of <span class="RktSym">list-pick</span>, let’s
|
||
|
look at the actual problem, the choice of inputs. The goal of the example
|
||
|
step is to cover the input space as much as possible. We do so by picking
|
||
|
one input per clause in the description of complex forms of data. Here this
|
||
|
procedure suggests we pick at least two elements from each class because
|
||
|
each data definition has two clauses. We choose <span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span> and
|
||
|
<span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="stt"> </span><span class="RktVal">'</span><span class="RktVal">a</span><span class="stt"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span><span class="RktPn">)</span> for the first argument, and <span class="RktVal">0</span> and
|
||
|
<span class="RktVal">3</span> for the latter. Two choices per argument means four examples
|
||
|
total; after all, there is no immediately obvious connection between the
|
||
|
two arguments and no restriction in the signature.</p><p><div class="SIntrapara">As it turns out, only one of these pairings produces a proper result; the
|
||
|
remaining ones choose a position that does not exist because the list
|
||
|
doesn’t contain enough symbols:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._check-error%29%29" class="RktStxLink" data-pltdoc="x">check-error</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">list-pick</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span><span class="hspace"> </span><span class="RktVal">0</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">"list too short"</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._check-expect%29%29" class="RktStxLink" data-pltdoc="x">check-expect</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">list-pick</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">a</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">0</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">a</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._check-error%29%29" class="RktStxLink" data-pltdoc="x">check-error</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">list-pick</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span><span class="hspace"> </span><span class="RktVal">3</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">"list too short"</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">The function is expected to signal an error, and we pick our favorite
|
||
|
message here.</div></p><p>Stop! Put these fragments into DrRacket’s definitions area and run the partial
|
||
|
program.</p><p>The discussion on examples indicates that there are indeed four independent
|
||
|
cases that we must inspect for the design of the function. One way to
|
||
|
discover these cases is to arrange the conditions for each of the clauses
|
||
|
into a two-dimensional table:</p><p><div class="SIntrapara"><blockquote><table cellspacing="0" cellpadding="0" style="border-collapse: collapse;"><tr><td style="border-bottom: 1px solid black;; border-right: 1px solid black;"><p></p></td><td style="border-bottom: 1px solid black;; border-right: 1px solid black;"><p><span class="hspace"> </span></p></td><td style="border-bottom: 1px solid black;"><p><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._empty~3f%29%29" class="RktValLink" data-pltdoc="x">empty?</a></span><span class="stt"> </span><span class="RktSym">l</span><span class="RktPn">)</span> </p></td><td style="border-bottom: 1px solid black;"><p><span class="hspace"> </span></p></td><td style="border-bottom: 1px solid black;"><p><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons~3f%29%29" class="RktValLink" data-pltdoc="x">cons?</a></span><span class="stt"> </span><span class="RktSym">l</span><span class="RktPn">)</span> </p></td></tr><tr><td style="border-right: 1px solid black;"><p><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~3d%29%29" class="RktValLink" data-pltdoc="x">=</a></span><span class="stt"> </span><span class="RktSym">n</span><span class="stt"> </span><span class="RktVal">0</span><span class="RktPn">)</span> </p></td><td style="border-right: 1px solid black;"><p><span class="hspace"> </span></p></td><td><p></p></td><td><p><span class="hspace"> </span></p></td><td><p></p></td></tr><tr><td style="border-right: 1px solid black;"><p><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~3e%29%29" class="RktValLink" data-pltdoc="x">></a></span><span class="stt"> </span><span class="RktSym">n</span><span class="stt"> </span><span class="RktVal">0</span><span class="RktPn">)</span> </p></td><td style="border-right: 1px solid black;"><p><span class="hspace"> </span></p></td><td><p></p></td><td><p><span class="hspace"> </span></p></td><td><p></p></td></tr></table></blockquote></div><div class="SIntrapara">The horizontal dimension of the table lists those questions that
|
||
|
<span class="RktSym">list-pick</span> must ask about lists; the vertical dimension lists the
|
||
|
questions about natural numbers. By this arrangement, we naturally get four
|
||
|
squares, where each represents the case when both the
|
||
|
conditions on the horizontal and the vertical axis are true.</div></p><p><div class="SIntrapara">Our table suggests that the <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span> for the function template has
|
||
|
four clauses. We can figure out the appropriate condition for each of these
|
||
|
clauses by <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._and%29%29" class="RktStxLink" data-pltdoc="x">and</a></span>-ing the horizontal and vertical condition for each
|
||
|
box in the table:
|
||
|
</div><div class="SIntrapara"><blockquote><table cellspacing="0" cellpadding="0" style="border-collapse: collapse;"><tr><td style="border-bottom: 1px solid black;; border-right: 1px solid black;"><p></p></td><td style="border-bottom: 1px solid black;; border-right: 1px solid black;"><p><span class="hspace"> </span></p></td><td style="border-bottom: 1px solid black;"><p><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._empty~3f%29%29" class="RktValLink" data-pltdoc="x">empty?</a></span><span class="stt"> </span><span class="RktSym">l</span><span class="RktPn">)</span> </p></td><td style="border-bottom: 1px solid black;"><p><span class="hspace"> </span></p></td><td style="border-bottom: 1px solid black;"><p><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons~3f%29%29" class="RktValLink" data-pltdoc="x">cons?</a></span><span class="stt"> </span><span class="RktSym">l</span><span class="RktPn">)</span> </p></td></tr><tr><td style="border-right: 1px solid black;"><p><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~3d%29%29" class="RktValLink" data-pltdoc="x">=</a></span><span class="stt"> </span><span class="RktSym">n</span><span class="stt"> </span><span class="RktVal">0</span><span class="RktPn">)</span> </p></td><td style="border-right: 1px solid black;"><p><span class="hspace"> </span></p></td><td><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._and%29%29" class="RktStxLink" data-pltdoc="x">and</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._empty~3f%29%29" class="RktValLink" data-pltdoc="x">empty?</a></span><span class="hspace"> </span><span class="RktSym">l</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~3d%29%29" class="RktValLink" data-pltdoc="x">=</a></span><span class="hspace"> </span><span class="RktSym">n</span><span class="hspace"> </span><span class="RktVal">0</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></td><td><p><span class="hspace"> </span></p></td><td><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._and%29%29" class="RktStxLink" data-pltdoc="x">and</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons~3f%29%29" class="RktValLink" data-pltdoc="x">cons?</a></span><span class="hspace"> </span><span class="RktSym">l</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediat
|
||
|
table into a conditional:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">list-pick</span><span class="hspace"> </span><span class="RktSym">l</span><span class="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._and%29%29" class="RktStxLink" data-pltdoc="x">and</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~3d%29%29" class="RktValLink" data-pltdoc="x">=</a></span><span class="hspace"> </span><span class="RktSym">n</span><span class="hspace"> </span><span class="RktVal">0</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._empty~3f%29%29" class="RktValLink" data-pltdoc="x">empty?</a></span><span class="hspace"> </span><span class="RktSym">l</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._and%29%29" class="RktStxLink" data-pltdoc="x">and</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~3e%29%29" class="RktValLink" data-pltdoc="x">></a></span><span class="hspace"> </span><span class="RktSym">n</span><span class="hspace"> </span><span class="RktVal">0</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._empty~3f%29%29" class="RktValLink" data-pltdoc="x">empty?</a></span><span class="hspace"> </span><span class="RktSym">l</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-l
|
||
|
possibilities and to focus on each individually as we add selector
|
||
|
expressions to each <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span> clause:</p><p><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">list-pick</span><span class="hspace"> </span><span class="RktSym">l</span><span class="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._and%29%29" class="RktStxLink" data-pltdoc="x">and</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~3d%29%29" class="RktValLink" data-pltdoc="x">=</a></span><span class="hspace"> </span><span class="RktSym">n</span><span class="hspace"> </span><span class="RktVal">0</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._empty~3f%29%29" class="RktValLink" data-pltdoc="x">empty?</a></span><span class="hspace"> </span><span class="RktSym">l</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._and%29%29" class="RktStxLink" data-pltdoc="x">and</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~3e%29%29" class="RktValLink" data-pltdoc="x">></a></span><span class="hspace"> </span><span class="RktSym">n</span><span class="hspace"> </span><span class="RktVal">0</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._empty~3f%29%29" class="RktValLink" data-pltdoc="x">empty?</a></span><span class="hspace"> </span><span class="RktSym">l</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-l
|
||
|
<span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span> clause for non-empty lists contains two selector expressions.
|
||
|
The second argument, <span class="RktSym">n</span>, belongs to <a href="part_two.html#%28tech._n%29" class="techoutside" data-pltdoc="x"><span class="techinside">N</span></a>, and the template’s
|
||
|
<span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span> clause for non-<span class="RktVal">0</span> numbers needs only one selector
|
||
|
expression. In those cases where either <span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._empty~3f%29%29" class="RktValLink" data-pltdoc="x">empty?</a></span><span class="stt"> </span><span class="RktSym">l</span><span class="RktPn">)</span> or <span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~3d%29%29" class="RktValLink" data-pltdoc="x">=</a></span><span class="stt"> </span><span class="RktSym">n</span><span class="stt"> </span><span class="RktVal">0</span><span class="RktPn">)</span> holds, the respective argument is atomic and there is no need for a
|
||
|
corresponding selector expression.</div></p><p><div class="SIntrapara">The final step of the template construction demands that we annotate the
|
||
|
template with recursions where the results of selector expressions belong
|
||
|
to the same class as the inputs. For this first example, we focus on the
|
||
|
last <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span> clause, which contains selector expressions for both
|
||
|
arguments. It is, however, unclear how to form the natural recursions. If
|
||
|
we disregard the purpose of the function, there are three possible recursions:
|
||
|
</div><div class="SIntrapara"><ol><li><p><span class="RktPn">(</span><span class="RktSym">list-pick</span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._rest%29%29" class="RktValLink" data-pltdoc="x">rest</a></span><span class="stt"> </span><span class="RktSym">l</span><span class="RktPn">)</span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._sub1%29%29" class="RktValLink" data-pltdoc="x">sub1</a></span><span class="stt"> </span><span class="RktSym">n</span><span class="RktPn">)</span><span class="RktPn">)</span></p></li><li><p><span class="RktPn">(</span><span class="RktSym">list-pick</span><span class="stt"> </span><span class="RktSym">l</span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._sub1%29%29" class="RktValLink" data-pltdoc="x">sub1</a></span><span class="stt"> </span><span class="RktSym">n</span><span class="RktPn">)</span><span class="RktPn">)</span></p></li><li><p><span class="RktPn">(</span><span class="RktSym">list-pick</span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._rest%29%29" class="RktValLink" data-pltdoc="x">rest</a></span><span class="stt"> </span><span class="RktSym">l</span><span class="RktPn">)</span><span class="stt"> </span><span class="RktSym">n</span><span class="RktPn">)</span></p></li></ol></div><div class="SIntrapara">Each one represents a feasible combination of the available expressions.
|
||
|
Since we cannot know which one matters or whether all three matter, we move
|
||
|
on to the next development stage.</div></p><blockquote class="Figure"><blockquote class="Centerfigure"><blockquote class="FigureInside"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">[</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> </span><a href="i2-3.html#%28tech._symbol%29" class="techoutside" data-pltdoc="x"><span class="techinside">Symbol</span></a><span class="RktCmt">] </span><a href="part_two.html#%28tech._n%29" class="techoutside" data-pltdoc="x"><span class="techinside">N</span></a><span class="RktCmt"> -> </span><a href="i2-3.html#%28tech._symbol%29" class="techoutside" data-pltdoc="x"><span class="techinside">Symbol</span></a></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">extracts the </span><span class="RktSym">n</span><span class="RktCmt">th symbol from </span><span class="RktSym">l</span><span class="RktCmt">; </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">signals an error if there is no such symbol</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">list-pick</span><span class="hspace"> </span><span class="RktSym">l</span><span class="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._and%29%29" class="RktStxLink" data-pltdoc="x">and</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~3d%29%29" class="RktValLink" data-pltdoc="x">=</a></span><span class="hspace"> </span><span class="RktSym">n</span><span class="hspace"> </span><span class="RktVal">0</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._empty~3f%29%29" class="RktValLink" data-pltdoc="x">empty?</a></span><span class="hspace"> </span><span class="RktSym">l</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._error%29%29" class="RktValLink" data-pltdoc="x">error</a></span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">list-pick</span><span class="hspace"> </span><span class="RktVal">"list too short"</span><span class="RktPn">)</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-l
|
||
|
<span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span> clause in the template and decide what a proper answer is:
|
||
|
</div><div class="SIntrapara"><ol><li><p>If <span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._and%29%29" class="RktStxLink" data-pltdoc="x">and</a></span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~3d%29%29" class="RktValLink" data-pltdoc="x">=</a></span><span class="stt"> </span><span class="RktSym">n</span><span class="stt"> </span><span class="RktVal">0</span><span class="RktPn">)</span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._empty~3f%29%29" class="RktValLink" data-pltdoc="x">empty?</a></span><span class="stt"> </span><span class="RktSym">l</span><span class="RktPn">)</span><span class="RktPn">)</span> holds, <span class="RktSym">list-pick</span> must
|
||
|
pick the first symbol from an empty list, which is impossible. The
|
||
|
answer must be an error signal.</p></li><li><p>If <span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._and%29%29" class="RktStxLink" data-pltdoc="x">and</a></span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~3e%29%29" class="RktValLink" data-pltdoc="x">></a></span><span class="stt"> </span><span class="RktSym">n</span><span class="stt"> </span><span class="RktVal">0</span><span class="RktPn">)</span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._empty~3f%29%29" class="RktValLink" data-pltdoc="x">empty?</a></span><span class="stt"> </span><span class="RktSym">l</span><span class="RktPn">)</span><span class="RktPn">)</span> holds, <span class="RktSym">list-pick</span> is
|
||
|
again asked to pick a symbol from an empty list.</p></li><li><p>If <span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._and%29%29" class="RktStxLink" data-pltdoc="x">and</a></span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~3d%29%29" class="RktValLink" data-pltdoc="x">=</a></span><span class="stt"> </span><span class="RktSym">n</span><span class="stt"> </span><span class="RktVal">0</span><span class="RktPn">)</span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons~3f%29%29" class="RktValLink" data-pltdoc="x">cons?</a></span><span class="stt"> </span><span class="RktSym">l</span><span class="RktPn">)</span><span class="RktPn">)</span> holds, <span class="RktSym">list-pick</span> is
|
||
|
supposed to produce the first symbol from <span class="RktSym">l</span>. The selector expression
|
||
|
<span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._first%29%29" class="RktValLink" data-pltdoc="x">first</a></span><span class="stt"> </span><span class="RktSym">l</span><span class="RktPn">)</span> is the answer.</p></li><li><p><div class="SIntrapara">If <span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._and%29%29" class="RktStxLink" data-pltdoc="x">and</a></span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~3e%29%29" class="RktValLink" data-pltdoc="x">></a></span><span class="stt"> </span><span class="RktSym">n</span><span class="stt"> </span><span class="RktVal">0</span><span class="RktPn">)</span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons~3f%29%29" class="RktValLink" data-pltdoc="x">cons?</a></span><span class="stt"> </span><span class="RktSym">l</span><span class="RktPn">)</span><span class="RktPn">)</span> holds, we must analyze what the
|
||
|
available expressions compute. As we have seen, it is a good idea to work
|
||
|
through an existing example for this step. We pick a shortened variant of
|
||
|
the first example:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._check-expect%29%29" class="RktStxLink" data-pltdoc="x">check-expect</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">list-pick</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">a</span><span class="hspace"> </span><span class="RktVal">b</span><span class="RktVal">)</span><span class="hspace"> </span><span class="RktVal">1</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">b</span><span class="RktPn">)</span></p></blockquote></div><div class="SIntrapara">Here is what the three natural recursions compute with these values:
|
||
|
</div><div class="SIntrapara"><ol><li><p><span class="RktPn">(</span><span class="RktSym">list-pick</span><span class="stt"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">b</span><span class="RktVal">)</span><span class="stt"> </span><span class="RktVal">0</span><span class="RktPn">)</span> produces <span class="RktVal">'</span><span class="RktVal">b</span>;</p></li><li><p><span class="RktPn">(</span><span class="RktSym">list-pick</span><span class="stt"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">a</span><span class="stt"> </span><span class="RktVal">b</span><span class="RktVal">)</span><span class="stt"> </span><span class="RktVal">0</span><span class="RktPn">)</span> evaluates to <span class="RktVal">'</span><span class="RktVal">a</span>, the
|
||
|
wrong answer;</p></li><li><p>and <span class="RktPn">(</span><span class="RktSym">list-pick</span><span class="stt"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">b</span><span class="RktVal">)</span><span class="stt"> </span><span class="RktVal">1</span><span class="RktPn">)</span> signals an error.</p></li></ol></div><div class="SIntrapara">From this, we conclude that <span class="RktPn">(</span><span class="RktSym">list-pick</span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._rest%29%29" class="RktValLink" data-pltdoc="x">rest</a></span><span class="stt"> </span><span class="RktSym">l</span><span class="RktPn">)</span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._sub1%29%29" class="RktValLink" data-pltdoc="x">sub1</a></span><span class="stt"> </span><span class="RktSym">n</span><span class="RktPn">)</span><span class="RktPn">)</span> computes
|
||
|
the desired answer in the last <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span> clause.</div></p></li></ol></div></p><p><div class="SIntrapara"><a name="(counter._(exercise._ex~3atree-pick))"></a><span style="font-weight: bold">Exercise</span> 390. Design the function <span class="RktSym">tree-pick</span>. The
|
||
|
function consumes a tree of symbols and a list of directions:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define-struct%29%29" class="RktStxLink" data-pltdoc="x">define-struct</a></span><span class="hspace"> </span><span class="RktSym">branch</span><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym"><a href="https://docs.racket-lang.org/teachpack/2htdpuniverse.html#%28form._world._%28%28lib._2htdp%2Funiverse..rkt%29._left%29%29" class="RktStxLink" data-pltdoc="x">left</a></span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/teachpack/2htdpuniverse.html#%28form._world._%28%28lib._2htdp%2Funiverse..rkt%29._right%29%29" class="RktStxLink" data-pltdoc="x">right</a></span><span class="RktPn">]</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">A </span><a name="(tech._to)"></a><span style="font-style: italic">TOS</span><span class="RktCmt"> is one of:</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">–</span><span class="RktCmt"> </span><a href="i2-3.html#%28tech._symbol%29" class="techoutside" data-pltdoc="x"><span class="techinside">Symbol</span></a></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">–</span><span class="RktCmt"> </span><span class="RktPn">(</span><span class="RktSym">make-branch</span><span class="stt"> </span><a href="part_four.html#%28tech._to%29" class="techoutside" data-pltdoc="x"><span class="techinside">TOS</span></a><span class="stt"> </span><a href="part_four.html#%28tech._to%29" class="techoutside" data-pltdoc="x"><span class="techinside">TOS</span></a><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">A </span><a name="(tech._direction)"></a><span style="font-style: italic">Direction</span><span class="RktCmt"> is one of:</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">–</span><span class="RktCmt"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._quote%29%29" class="RktStxLink" data-pltdoc="x">'</a></span><span class="RktSym"><a href="https://docs.racket-lang.org/teachpack/2htdpuniverse.html#%28form._world._%28%28lib._2htdp%2Funiverse..rkt%29._left%29%29" class="RktStxLink" data-pltdoc="x">left</a></span><span class="RktMeta"></span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">–</span><span class="RktCmt"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._quote%29%29" class="RktStxLink" data-pltdoc="x">'</a></span><span class="RktSym"><a href="https://docs.racket-lang.org/teachpack/2htdpuniverse.html#%28form._world._%28%28lib._2htdp%2Funiverse..rkt%29._right%29%29" class="RktStxLink" data-pltdoc="x">right</a></span><span class="RktMeta"></span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">A list of </span><a href="part_four.html#%28tech._direction%29" class="techoutside" data-pltdoc="x"><span class="techinside">Direction</span></a><span class="RktCmt">s is also called a path. </span></td></tr></table></blockquote></div><div class="SIntrapara">Clearly a <a href="part_four.html#%28tech._direction%29" class="techoutside" data-pltdoc="x"><span class="techinside">Direction</span></a> tells the fun
|
||
|
the right branch in a nonsymbolic tree. What is the result of the
|
||
|
<span class="RktSym">tree-pick</span> function? Don’t forget to formulate a full signature.
|
||
|
The function signals an error when given a symbol and a non-empty path. <a href="part_four.html#%28counter._%28exercise._ex~3atree-pick%29%29" class="ex-end" data-pltdoc="x"></a></div></p><h4>23.4<tt> </tt><a name="(part._sec~3atwo-inputs~3asimplify)"></a>Function Simplification</h4><p><div class="SIntrapara">The <span class="RktSym">list-pick</span> function in <a href="part_four.html#%28counter._%28figure._fig~3alist-pick%29%29" data-pltdoc="x">figure <span class="FigureRef">134</span></a> is far more
|
||
|
complicated than necessary. The first two <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span> clauses signal an
|
||
|
error. That is, if either
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._and%29%29" class="RktStxLink" data-pltdoc="x">and</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~3d%29%29" class="RktValLink" data-pltdoc="x">=</a></span><span class="hspace"> </span><span class="RktSym">n</span><span class="hspace"> </span><span class="RktVal">0</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._empty~3f%29%29" class="RktValLink" data-pltdoc="x">empty?</a></span><span class="hspace"> </span><span class="RktSym">alos</span><span class="RktPn">)</span><span class="RktPn">)</span></p></blockquote></div><div class="SIntrapara">or
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._and%29%29" class="RktStxLink" data-pltdoc="x">and</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~3e%29%29" class="RktValLink" data-pltdoc="x">></a></span><span class="hspace"> </span><span class="RktSym">n</span><span class="hspace"> </span><span class="RktVal">0</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._empty~3f%29%29" class="RktValLink" data-pltdoc="x">empty?</a></span><span class="hspace"> </span><span class="RktSym">alos</span><span class="RktPn">)</span><span class="RktPn">)</span></p></blockquote></div><div class="SIntrapara">holds, the answer is an error. We can translate this observation into code:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">list-pick</span><span class="hspace"> </span><span class="RktSym">alos</span><span class="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._or%29%29" class="RktStxLink" data-pltdoc="x">or</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._and%29%29" class="RktStxLink" data-pltdoc="x">and</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~3d%29%29" class="RktValLink" data-pltdoc="x">=</a></span><span class="hspace"> </span><span class="RktSym">n</span><span class="hspace"> </span><span class="RktVal">0</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._empty~3f%29%29" class="RktValLink" data-pltdoc="x">empty?</a></span><span class="hspace"> </span><span class="RktSym">alos</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._and%29%29" class="RktStxLink" data-pltdoc="x">and</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~3e%29%29" class="RktValLink" data-pltdoc="x">></a></span><span class="hspace"> </span><span class="RktSym">n</span><span class="hspace"> </span><span class="RktVal">0</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._empty~3f%29%29" class="RktValLink" data-pltdoc="x">empty?</a></span><span class="hspace"> </span><span class="RktSym">alos</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._error%29%29" class="RktValLink" data-pltdoc="x">error</a></span><span class="hspace"> </span><span class="RktVal">'</span><span class=
|
||
|
algebraic laws concerning Booleans:<span class="refelem"><span class="refcolumn"><span class="refcontent">These equations are known as
|
||
|
de Morgan’s laws.</span></span></span>
|
||
|
</div><div class="SIntrapara"><blockquote><table cellspacing="0" cellpadding="0"><tr><td valign="top"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._or%29%29" class="RktStxLink" data-pltdoc="x">or</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._and%29%29" class="RktStxLink" data-pltdoc="x">and</a></span><span class="hspace"> </span><span class="RktSym">bexp1</span><span class="hspace"> </span><span class="RktSym">a-bexp</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._and%29%29" class="RktStxLink" data-pltdoc="x">and</a></span><span class="hspace"> </span><span class="RktSym">bexp2</span><span class="hspace"> </span><span class="RktSym">a-bexp</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></td><td valign="top"><p><span class="hspace"> </span></p></td><td valign="top"><p><span class="RktSym">==</span></p></td><td valign="top"><p><span class="hspace"> </span></p></td><td valign="top"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._and%29%29" class="RktStxLink" data-pltdoc="x">and</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._or%29%29" class="RktStxLink" data-pltdoc="x">or</a></span><span class="hspace"> </span><span class="RktSym">bexp1</span><span class="hspace"> </span><span class="RktSym">bexp2</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktSym">a-bexp</span><span class="RktPn">)</span></td></tr></table></td></tr></table></blockquote></div><div class="SIntrapara">A similar law applies when the sub-expressions of the <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._and%29%29" class="RktStxLink" data-pltdoc="x">and</a></span>s are
|
||
|
swapped. Applying these laws to <span class="RktSym">list-pick</span> yields this:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">list-pick</span><span class="hspace"> </span><span class="RktSym">n</span><span class="hspace"> </span><span class="RktSym">alos</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._and%29%29" class="RktStxLink" data-pltdoc="x">and</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._or%29%29" class="RktStxLink" data-pltdoc="x">or</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~3d%29%29" class="RktValLink" data-pltdoc="x">=</a></span><span class="hspace"> </span><span class="RktSym">n</span><span class="hspace"> </span><span class="RktVal">0</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~3e%29%29" class="RktValLink" data-pltdoc="x">></a></span><span class="hspace"> </span><span class="RktSym">n</span><span class="hspace"> </span><span class="RktVal">0</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._empty~3f%29%29" class="RktValLink" data-pltdoc="x">empty?</a></span><span class="hspace"> </span><span class="RktSym">alos</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._error%29%29" class="RktValLink" data-pltdoc="x">error</a></span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">list-pick</span><span class="hspace"> </span><span class="RktVal">"list too short"</span><span class="RktPn">)</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._and%29%29" class="RktStxLink" data-pltdoc="x">and</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~3d%29%29" class="RktValLink" dat
|
||
|
because <span class="RktSym">n</span> belongs to <a href="part_two.html#%28tech._n%29" class="techoutside" data-pltdoc="x"><span class="techinside">N</span></a>. Since <span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._and%29%29" class="RktStxLink" data-pltdoc="x">and</a></span><span class="stt"> </span><span class="RktVal">#true</span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._empty~3f%29%29" class="RktValLink" data-pltdoc="x">empty?</a></span><span class="stt"> </span><span class="RktSym">alos</span><span class="RktPn">)</span><span class="RktPn">)</span>
|
||
|
is equivalent to <span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._empty~3f%29%29" class="RktValLink" data-pltdoc="x">empty?</a></span><span class="stt"> </span><span class="RktSym">alos</span><span class="RktPn">)</span>, we can rewrite the function again:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">list-pick</span><span class="hspace"> </span><span class="RktSym">alos</span><span class="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._empty~3f%29%29" class="RktValLink" data-pltdoc="x">empty?</a></span><span class="hspace"> </span><span class="RktSym">alos</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._error%29%29" class="RktValLink" data-pltdoc="x">error</a></span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">list-pick</span><span class="hspace"> </span><span class="RktVal">"list too short"</span><span class="RktPn">)</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._and%29%29" class="RktStxLink" data-pltdoc="x">and</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~3d%29%29" class="RktValLink" data-pltdoc="x">=</a></span><span class="hspace"> </span><span class="RktSym">n</span><span class="hspace"> </span><span class="RktVal">0</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons~3f%29%29" class="RktValLink" data-pltdoc="x">cons?</a></span><span class="hspace"> </span><span class="RktSym">alos</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._first%29%29" class="RktValLink" data-pltdoc="x">first</a></span><span class="hspace"> </span><span class="RktSym">alos</span><span class="RktPn">)</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._and%29%29" class="RktStxLink" data-pltdoc="x">and</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-l
|
||
|
in <a href="part_four.html#%28counter._%28figure._fig~3alist-pick%29%29" data-pltdoc="x">figure <span class="FigureRef">134</span></a>, but we can do even better than this. Compare
|
||
|
the first condition in the latest version of <span class="RktSym">list-pick</span> with the
|
||
|
second and third. Since the first <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span> clause filters out all
|
||
|
those cases when <span class="RktSym">alos</span> is empty, <span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons~3f%29%29" class="RktValLink" data-pltdoc="x">cons?</a></span><span class="stt"> </span><span class="RktSym">alos</span><span class="RktPn">)</span> in the last
|
||
|
two clauses is always going to evaluate to <span class="RktVal">#true</span>. If we replace
|
||
|
the condition with <span class="RktVal">#true</span> and simplify the <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._and%29%29" class="RktStxLink" data-pltdoc="x">and</a></span> expressions
|
||
|
again, we get a three-line version of <span class="RktSym">list-pick</span></p><blockquote class="Figure"><blockquote class="Centerfigure"><blockquote class="FigureInside"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktSym">list-pick</span><span class="RktCmt">: [</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> </span><a href="i2-3.html#%28tech._symbol%29" class="techoutside" data-pltdoc="x"><span class="techinside">Symbol</span></a><span class="RktCmt">] </span><a href="part_two.html#%28tech._n%29" class="techoutside" data-pltdoc="x"><span class="techinside">N</span></a><span class="RktCmt">[>= 0] -> </span><a href="i2-3.html#%28tech._symbol%29" class="techoutside" data-pltdoc="x"><span class="techinside">Symbol</span></a></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">determines the </span><span class="RktSym">nth</span><span class="RktCmt"> symbol from </span><span class="RktSym">alos</span><span class="RktCmt">, counting from </span><span class="RktVal">0</span><span class="RktCmt">;</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">signals an error if there is no </span><span class="RktSym">n</span><span class="RktCmt">th symbol</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">list-pick</span><span class="hspace"> </span><span class="RktSym">alos</span><span class="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._empty~3f%29%29" class="RktValLink" data-pltdoc="x">empty?</a></span><span class="hspace"> </span><span class="RktSym">alos</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._error%29%29" class="RktValLink" data-pltdoc="x">error</a></span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">list-pick</span><span class="hspace"> </span><span class="RktVal">"list too short"</span><span class="RktPn">)</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~3d%29%29" class="RktValLink" data-pltdoc="x">=</a></span><span class="hspace"> </span><span class="RktSym">n</span><span class="hspace"> </span><span class="RktVal">0</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._first%29%29" class="RktValLin
|
||
|
<span class="RktSym">list-pick</span>. While it is far simpler than the original, it is
|
||
|
important to understand that we designed the original in a systematic
|
||
|
manner and that we were able to transform the first into the second with
|
||
|
well-established algebraic laws. We can therefore trust this simple
|
||
|
version. If we try to find the simple versions of functions directly, we
|
||
|
sooner or later fail to take care of a case in our analysis, and we are
|
||
|
guaranteed to produce flawed programs.</p><p><a name="(counter._(exercise._ex~3areplace-eol-simp))"></a><span style="font-weight: bold">Exercise</span> 391. Design <span class="RktSym">replace-eol-with</span> using the
|
||
|
strategy of <a href="part_four.html#%28part._sec~3atwo-inputs~3acase3%29" data-pltdoc="x">Processing Two Lists Simultaneously: Case 3</a>. Start from the tests. Simplify
|
||
|
the result systematically. <a href="part_four.html#%28counter._%28exercise._ex~3areplace-eol-simp%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._(exercise._ex~3atree-ref-simpl))"></a><span style="font-weight: bold">Exercise</span> 392. Simplify the function <span class="RktSym">tree-pick</span>
|
||
|
from <a href="part_four.html#%28counter._%28exercise._ex~3atree-pick%29%29" data-pltdoc="x">exercise 390</a>. <a href="part_four.html#%28counter._%28exercise._ex~3atree-ref-simpl%29%29" class="ex-end" data-pltdoc="x"></a></p><h4>23.5<tt> </tt><a name="(part._sec~3atwo-inputs~3adesign)"></a>Designing Functions that Consume Two Complex Inputs</h4><p><div class="SIntrapara">The proper approach to designing functions of two (or more) complex
|
||
|
arguments is to follow the <a name="(idx._(gentag._562))"></a>general recipe. You must conduct a data
|
||
|
analysis and define the relevant classes of data. If the use of parametric
|
||
|
definitions such as <a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a> and short-hand examples such as <span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">1</span><span class="stt"> </span><span class="RktVal">b</span><span class="stt"> </span><span class="RktVal">&</span><span class="RktVal">)</span> confuses you, expand them so that the constructors become
|
||
|
explicit. Next you need a function signature and purpose. At this point,
|
||
|
you can think ahead and decide which of the following three situations you
|
||
|
are facing:
|
||
|
</div><div class="SIntrapara"><ol><li><p>If one of the parameters plays a dominant role, think of the other as
|
||
|
an atomic piece of data as far as the function is concerned.</p></li><li><p>In some cases the parameters range over the same class of values and
|
||
|
must have the same size. For example, two lists must have the same
|
||
|
length, or two web pages must have the same length and where one of them
|
||
|
contains an embedded page, the other one does, too. If the two parameters
|
||
|
have this equal status and the purpose suggests that they are processed in
|
||
|
a synchronized manner, you choose one parameter, organize the function
|
||
|
around it, and traverse the other in a parallel manner.</p></li><li><p>If there is no obvious connection between the two parameters, you
|
||
|
must analyze all possible cases with examples. Then use this analysis to
|
||
|
develop the template, especially the recursive parts.</p></li></ol></div></p><p><div class="SIntrapara">Once you decide that a function falls into the third category, develop a
|
||
|
two-dimensional table to make sure that no case falls through the
|
||
|
cracks. Let’s use a nontrivial pair of data definitions to explain this
|
||
|
idea again:
|
||
|
</div><div class="SIntrapara"><blockquote class="SVInsetFlow"><table cellspacing="0" cellpadding="0"><tr><td align="left" valign="top"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">An </span><a name="(tech._lod)"></a><span style="font-style: italic">LOD</span><span class="RktCmt"> is one of: </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">–</span><span class="RktCmt"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">–</span><span class="RktCmt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="stt"> </span><a href="part_four.html#%28tech._direction%29" class="techoutside" data-pltdoc="x"><span class="techinside">Direction</span></a><span class="stt"> </span><a href="part_four.html#%28tech._lod%29" class="techoutside" data-pltdoc="x"><span class="techinside">LOD</span></a><span class="RktPn">)</span></td></tr></table></td><td align="left" valign="top"><p><span class="hspace"> </span></p></td><td align="left" valign="top"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">A </span><a name="(tech._tid)"></a><span style="font-style: italic">TID</span><span class="RktCmt"> is one of: </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">–</span><span class="RktCmt"> </span><a href="i2-3.html#%28tech._symbol%29" class="techoutside" data-pltdoc="x"><span class="techinside">Symbol</span></a></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">–</span><span class="RktCmt"> </span><span class="RktPn">(</span><span class="RktSym">make-binary</span><span class="stt"> </span><a href="part_four.html#%28tech._tid%29" class="techoutside" data-pltdoc="x"><span class="techinside">TID</span></a><span class="stt"> </span><a href="part_four.html#%28tech._tid%29" class="techoutside" data-pltdoc="x"><span class="techinside">TID</span></a><span class="RktPn">)</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">–</span><span class="RktCmt"> </span><span class="RktPn">(</span><span class="RktSym">make-with</span><span class="stt"> </span><a href="part_four.html#%28tech._tid%29" class="techoutside" data-pltdoc="x"><span class="techinside">TID</span></a><span class="stt"> </span><a href="i2-3.html#%28tech._symbol%29" class="techoutside" data-pltdoc="x"><span class="techinside">Symbol</span></a><span class="stt"> </span><a href="part_four.html#%28tech._tid%29" class="techoutside" data-pltdoc="x"><span class="techinside">TID</span></a><span class="RktPn">)</span></td></tr></table></td></tr></table></blockquote></div><div class="SIntrapara">The left data definition is the usual list definition; the right one
|
||
|
is a three-clause variant of <a href="part_four.html#%28tech._to%29" class="techoutside" data-pltdoc="x"><span class="techinside">TOS</span></a>. It uses two structure type definitions:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define-struct%29%29" class="RktStxLink" data-pltdoc="x">define-struct</a></span><span class="hspace"> </span><span class="RktSym">with</span><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym">lft</span><span class="hspace"> </span><span class="RktSym">info</span><span class="hspace"> </span><span class="RktSym">rght</span><span class="RktPn">]</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define-struct%29%29" class="RktStxLink" data-pltdoc="x">define-struct</a></span><span class="hspace"> </span><span class="RktSym">binary</span><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym">lft</span><span class="hspace"> </span><span class="RktSym">rght</span><span class="RktPn">]</span><span class="RktPn">)</span></td></tr></table></blockquote></div></p><p><div class="SIntrapara">Assuming the function consumes an <a href="part_four.html#%28tech._lod%29" class="techoutside" data-pltdoc="x"><span class="techinside">LOD</span></a> and a <a href="part_four.html#%28tech._tid%29" class="techoutside" data-pltdoc="x"><span class="techinside">TID</span></a>, the table
|
||
|
that you should come up with has this shape:
|
||
|
</div><div class="SIntrapara"><blockquote><table cellspacing="0" cellpadding="0" style="border-collapse: collapse;"><tr><td style="border-bottom: 1px solid black;; border-right: 1px solid black;"><p></p></td><td style="border-bottom: 1px solid black;; border-right: 1px solid black;"><p><span class="hspace"> </span></p></td><td style="border-bottom: 1px solid black;"><p><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._empty~3f%29%29" class="RktValLink" data-pltdoc="x">empty?</a></span><span class="stt"> </span><span class="RktSym">l</span><span class="RktPn">)</span> </p></td><td style="border-bottom: 1px solid black;"><p><span class="hspace"> </span></p></td><td style="border-bottom: 1px solid black;"><p><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cons~3f%29%29" class="RktValLink" data-pltdoc="x">cons?</a></span><span class="stt"> </span><span class="RktSym">l</span><span class="RktPn">)</span> </p></td></tr><tr><td style="border-right: 1px solid black;"><p><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._symbol~3f%29%29" class="RktValLink" data-pltdoc="x">symbol?</a></span><span class="stt"> </span><span class="RktSym">t</span><span class="RktPn">)</span> </p></td><td style="border-right: 1px solid black;"><p><span class="hspace"> </span></p></td><td><p></p></td><td><p><span class="hspace"> </span></p></td><td><p></p></td></tr><tr><td style="border-right: 1px solid black;"><p><span class="RktPn">(</span><span class="RktSym">binary?</span><span class="stt"> </span><span class="RktSym">t</span><span class="RktPn">)</span> </p></td><td style="border-right: 1px solid black;"><p><span class="hspace"> </span></p></td><td><p></p></td><td><p><span class="hspace"> </span></p></td><td><p></p></td></tr><tr><td style="border-right: 1px solid black;"><p><span class="RktPn">(</span><span class="RktSym">with?</span><span class="stt"> </span><span class="RktSym">t</span><span class="RktPn">)</span> </p></td><td style="border-right: 1px solid black;"><p><span class="hspace"> </span></p></td><td><p></p></td><td><p><span class="hspace"> </span></p></td><td><p></p></td></tr></table></blockquote></div><div class="SIntrapara">Along the horizontal direction we enumerate the conditions that
|
||
|
recognize the sub-classes for the first parameter, here <a href="part_four.html#%28tech._lod%29" class="techoutside" data-pltdoc="x"><span class="techinside">LOD</span></a>, and
|
||
|
along the vertical direction we enumerate the conditions for the second
|
||
|
parameter, <a href="part_four.html#%28tech._tid%29" class="techoutside" data-pltdoc="x"><span class="techinside">TID</span></a>.</div></p><p>The table guides the development of both the function examples and
|
||
|
the function template. As explained, the examples must cover all possible
|
||
|
cases; that is, there must be at least one example for each cell in the
|
||
|
table. Similarly, the template must have one <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span> clause per
|
||
|
cell; its condition combines the horizontal and the vertical conditions in
|
||
|
an <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._and%29%29" class="RktStxLink" data-pltdoc="x">and</a></span> expression. Each <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._cond%29%29" class="RktStxLink" data-pltdoc="x">cond</a></span> clause, in turn, must
|
||
|
contain all feasible selector expressions for both parameters. If one of
|
||
|
the parameters is atomic, there is no need for a selector
|
||
|
expression. Finally, you need to be aware of the feasible natural
|
||
|
recursions. In general, all possible combinations of selector expressions
|
||
|
(and optionally, atomic arguments) are candidates for a natural
|
||
|
recursion. Because we can’t know which ones are necessary and which ones
|
||
|
aren’t, we keep them in mind for the coding step.</p><p>In summary, the design of multiparameter functions is just a variation on
|
||
|
the old design-recipe theme. The key idea is to translate the data
|
||
|
definitions into a table that shows all feasible and interesting
|
||
|
combinations. The development of function examples and the template
|
||
|
exploit the table as much as possible.</p><h4>23.6<tt> </tt><a name="(part._sec~3atwo-inputs~3aex)"></a>Finger Exercises: Two Inputs</h4><p><a name="(counter._(exercise._ex~3aset2))"></a><span style="font-weight: bold">Exercise</span> 393. <a href="part_two.html#%28counter._%28figure._fig~3asets-vs-lists%29%29" data-pltdoc="x">Figure <span class="FigureRef">62</span></a> presents two data
|
||
|
definitions for finite sets. Design the <span class="RktSym">union</span> function for the
|
||
|
representation of finite sets of your choice. It consumes two sets and
|
||
|
produces one that contains the elements of both.</p><p>Design <span class="RktSym">intersect</span> for the same set representation. It consumes two
|
||
|
sets and produces the set of exactly those elements that occur in both. <a href="part_four.html#%28counter._%28exercise._ex~3aset2%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._(exercise._ex~3amerge))"></a><span style="font-weight: bold">Exercise</span> 394. Design <span class="RktSym">merge</span>. The function consumes two
|
||
|
lists of numbers, sorted in ascending order. It produces a single sorted
|
||
|
list of numbers that contains all the numbers on both inputs lists. A
|
||
|
number occurs in the output as many times as it occurs on the two input
|
||
|
lists together. <a href="part_four.html#%28counter._%28exercise._ex~3amerge%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._(exercise._ex~3adrop-take))"></a><span style="font-weight: bold">Exercise</span> 395. Design <span class="RktSym">take</span>. It consumes a list
|
||
|
<span class="RktSym">l</span> and a natural number <span class="RktSym">n</span>. It produces the first
|
||
|
<span class="RktSym">n</span> items from <span class="RktSym">l</span> or all of <span class="RktSym">l</span> if it is too short.</p><p>Design <span class="RktSym">drop</span>. It consumes a list <span class="RktSym">l</span> and a natural number
|
||
|
<span class="RktSym">n</span>. Its result is <span class="RktSym">l</span> with the first <span class="RktSym">n</span> items
|
||
|
removed or just ’<span class="RktPn">(</span><span class="RktPn">)</span> if <span class="RktSym">l</span> is too short. <a href="part_four.html#%28counter._%28exercise._ex~3adrop-take%29%29" class="ex-end" data-pltdoc="x"></a></p><blockquote class="Figure"><blockquote class="Centerfigure"><blockquote class="FigureInside"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">An </span><a name="(tech._hm._word)"></a><span style="font-style: italic">HM-Word</span><span class="RktCmt"> is a [</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> </span><a href="part_two.html#%28tech._letter%29" class="techoutside" data-pltdoc="x"><span class="techinside">Letter</span></a><span class="RktCmt"> or </span><span class="RktVal">"_"</span><span class="RktCmt">]</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span style="font-weight: bold">interpretation</span><span class="RktCmt"> </span><span class="RktVal">"_"</span><span class="RktCmt"> represents a letter to be guessed </span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_four.html#%28tech._hm._word%29" class="techoutside" data-pltdoc="x"><span class="techinside">HM-Word</span></a><span class="RktCmt"> </span><a href="part_two.html#%28tech._n%29" class="techoutside" data-pltdoc="x"><span class="techinside">N</span></a><span class="RktCmt"> -> </span><a href="part_one.html#%28tech._string%29" class="techoutside" data-pltdoc="x"><span class="techinside">String</span></a></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">runs a simplistic hangman game, produces the current state</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">play</span><span class="hspace"> </span><span class="RktSym">the-pick</span><span class="hspace"> </span><span class="RktSym">time-limit</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._local%29%29" class="RktStxLink" data-pltdoc="x">local</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">the-word</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._explode%29%29" class="RktValLink" data-pltdoc="x">explode</a></span><span class="hspace"> </span><span class="RktSym">the-pick</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">the-guess</span><span class="hspace"> </span><span class="RktPn">(</span><span
|
||
|
player picks a word, the other player gets told how many letters the word
|
||
|
contains. The latter picks a letter and asks the first player whether
|
||
|
and where this letter occurs in the chosen word. The game is over after an
|
||
|
agreed-upon time or number of rounds.</p><p><a href="part_four.html#%28counter._%28figure._fig~3ahangman-game%29%29" data-pltdoc="x">Figure <span class="FigureRef">136</span></a> presents the essence of a time-limited
|
||
|
version of the game. See <a href="part_three.html#%28part._sec~3alocal-is-power%29" data-pltdoc="x">Local Definitions Add Expressive Power</a> for why
|
||
|
<span class="RktSym">checked-compare</span> is defined locally. <a name="(idx._(gentag._563))"></a></p><p>The goal of this exercise is to design <span class="RktSym">compare-word</span>, the central
|
||
|
function. It consumes the word to be guessed, a word <span class="RktSym">s</span> that
|
||
|
represents how much/little the guessing player has discovered, and the
|
||
|
current guess. The function produces <span class="RktSym">s</span> with all <span class="RktVal">"_"</span> where
|
||
|
the guess revealed a letter.</p><p><div class="SIntrapara">Once you have designed the function, run the program like this:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">LOCATION</span><span class="hspace"> </span><span class="RktVal">"/usr/share/dict/words"</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">on OS X</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">AS-LIST</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/teachpack/2htdpbatch-io.html#%28def._%28%28lib._2htdp%2Fbatch-io..rkt%29._read-lines%29%29" class="RktValLink" data-pltdoc="x">read-lines</a></span><span class="hspace"> </span><span class="RktSym">LOCATION</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">SIZE</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">length</span><span class="hspace"> </span><span class="RktSym">AS-LIST</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym">play</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list-ref%29%29" class="RktValLink" data-pltdoc="x">list-ref</a></span><span class="hspace"> </span><span class="RktSym">AS-LIST</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._random%29%29" class="RktValLink" data-pltdoc="x">random</a></span><span class="hspace"> </span><span class="RktSym">SIZE</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">10</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">See <a href="part_two.html#%28counter._%28figure._fig~3areading-a-dictionary%29%29" data-pltdoc="x">figure <span class="FigureRef">74</span></a> for an explanation. Enjoy and
|
||
|
refine as desired! <a href="part_four.html#%28counter._%28exercise._ex~3ahangman-list%29%29" class="ex-end" data-pltdoc="x"></a></div></p><p><a name="(counter._(exercise._ex~3awage-general))"></a><span style="font-weight: bold">Exercise</span> 397. In a factory, employees punch time cards as
|
||
|
they arrive in the morning and leave in the evening. Electronic time cards
|
||
|
contain an employee number and record the number of hours worked per week.
|
||
|
Employee records always contain the name of the employee, an employee
|
||
|
number, and a pay rate.<a name="(idx._(gentag._564))"></a></p><p>Design <span class="RktSym">wages*.v3</span>. The function consumes a list of employee records
|
||
|
and a list of time-card records. It produces a list of wage records, which
|
||
|
contain the name and weekly wage of an employee. The function signals an
|
||
|
error if it cannot find an employee record for a time card or vice
|
||
|
versa.</p><p><span style="font-weight: bold">Assumption</span> There is at most one time card per employee number. <a href="part_four.html#%28counter._%28exercise._ex~3awage-general%29%29" class="ex-end" data-pltdoc="x"></a></p><p><div class="SIntrapara"><a name="(counter._(exercise._ex~3apolyn))"></a><span style="font-weight: bold">Exercise</span> 398. A linear combination is the sum of many linear terms,
|
||
|
that is, products of variables and numbers. The latter are called
|
||
|
coefficients in this context. Here are some examples:
|
||
|
</div><div class="SIntrapara"><blockquote><table cellspacing="0" cellpadding="0"><tr><td><p><img src="pict_148.png" alt="image" width="22" height="8"/></p></td><td><p><span class="hspace"> </span></p></td><td><p><img src="pict_149.png" alt="image" width="65" height="10"/></p></td><td><p><span class="hspace"> </span></p></td><td><p><img src="pict_150.png" alt="image" width="102" height="10"/></p></td></tr></table></blockquote></div><div class="SIntrapara">In all examples, the coefficient of <span style="font-style: italic">x</span> is 5, that of
|
||
|
<span style="font-style: italic">y</span> is 17, and the one for <span style="font-style: italic">z</span> is 3.</div></p><p>If we are given values for variables, we can determine the value of a
|
||
|
polynomial. For example, if <span style="font-style: italic">x = </span>1<span style="font-style: italic"></span>0<span style="font-style: italic"></span>, the value of <img src="pict_151.png" alt="image" width="22" height="8"/> is
|
||
|
<span style="font-style: italic"></span>5<span style="font-style: italic"></span>0<span style="font-style: italic"></span>; if <span style="font-style: italic">x = </span>1<span style="font-style: italic"></span>0<span style="font-style: italic"></span> and <span style="font-style: italic">y = </span>1<span style="font-style: italic"></span>, the value of <img src="pict_152.png" alt="image" width="65" height="10"/> is
|
||
|
<span style="font-style: italic"></span>6<span style="font-style: italic"></span>7<span style="font-style: italic"></span>; and if <span style="font-style: italic">x = </span>1<span style="font-style: italic"></span>0<span style="font-style: italic"></span>, <span style="font-style: italic">y = </span>1<span style="font-style: italic"></span>, and <span style="font-style: italic">z = </span>2<span style="font-style: italic"></span>, the value
|
||
|
of <img src="pict_153.png" alt="image" width="102" height="10"/> is <span style="font-style: italic"></span>7<span style="font-style: italic"></span>3<span style="font-style: italic"></span>.</p><p><div class="SIntrapara">There are many different representations of linear combinations. We could,
|
||
|
for example, represent them with functions. An alternative representation is a
|
||
|
list of its coefficients. The above combinations would be represented as:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">5</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">5</span><span class="hspace"> </span><span class="RktVal">17</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">5</span><span class="hspace"> </span><span class="RktVal">17</span><span class="hspace"> </span><span class="RktVal">3</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">This choice of representation assumes a fixed order of variables.</div></p><p>Design <span class="RktSym">value</span>. The function consumes two equally long lists: a
|
||
|
linear combination and a list of variable values. It produces the value of
|
||
|
the combination for these values. <a href="part_four.html#%28counter._%28exercise._ex~3apolyn%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._(exercise._ex~3aperm-xmas))"></a><span style="font-weight: bold">Exercise</span> 399. Louise, Jane, Laura, Dana, and Mary decide to run
|
||
|
a lottery that assigns one gift recipient to each of them. Since Jane is a
|
||
|
developer, they ask her to write a program that performs this task in an
|
||
|
impartial manner. Of course, the program must not assign any of the sisters
|
||
|
to herself.</p><p><div class="SIntrapara">Here is the core of Jane’s program: <a name="(idx._(gentag._565))"></a> <a name="(idx._(gentag._566))"></a>
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">[</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> </span><a href="part_one.html#%28tech._string%29" class="techoutside" data-pltdoc="x"><span class="techinside">String</span></a><span class="RktCmt">] -> [</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> </span><a href="part_one.html#%28tech._string%29" class="techoutside" data-pltdoc="x"><span class="techinside">String</span></a><span class="RktCmt">] </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">picks a random non-identity arrangement of </span><span class="RktSym">names</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">gift-pick</span><span class="hspace"> </span><span class="RktSym">names</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">random-pick</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">non-same</span><span class="hspace"> </span><span class="RktSym">names</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">arrangements</span><span class="hspace"> </span><span class="RktSym">names</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">[</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> </span><a href="part_one.html#%28tech._string%29" class="techoutside" data-pltdoc="x"><span class="techinside">String</span></a><span class="RktCmt">] -> [</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> [</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> </span><a href="part_one.html#%28tech._string%29" class="techoutside" data-pltdoc="x"><span class="techinside">String</span></a><span class="RktCmt">]]</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">returns all possible permutations of </span><span class="RktSym">names</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">see </span><a href="part_two.html#%28counter._%28exercise._ex~3apermutations%29%29" data-pltdoc="x">exercise 213</a></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">arrangements</span><span class="hspace"> </span><span class="RktSym">names</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._
|
||
|
that do not agree with the original list at any place.</div></p><p><div class="SIntrapara">Your task is to design two auxiliary functions: <a name="(idx._(gentag._567))"></a> <a name="(idx._(gentag._568))"></a>
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">[</span><a href="part_three.html#%28tech._sim-dd._nelist._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">NEList-of</span></a><span class="RktCmt"> X] -> X </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">returns a random item from the list </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">random-pick</span><span class="hspace"> </span><span class="RktSym">l</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._first%29%29" class="RktValLink" data-pltdoc="x">first</a></span><span class="hspace"> </span><span class="RktSym">l</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">[</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> </span><a href="part_one.html#%28tech._string%29" class="techoutside" data-pltdoc="x"><span class="techinside">String</span></a><span class="RktCmt">] [</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> [</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> </span><a href="part_one.html#%28tech._string%29" class="techoutside" data-pltdoc="x"><span class="techinside">String</span></a><span class="RktCmt">]] </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">-> </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">[</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> [</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> </span><a href="part_one.html#%28tech._string%29" class="techoutside" data-pltdoc="x"><span class="techinside">String</span></a><span class="RktCmt">]]</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">produces the list of those lists in </span><span class="RktSym">ll</span><span class="RktCmt"> that do </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">not agree with </span><span class="RktSym">names</span><span class="RktCmt"> at any place </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">non-same</span><span class="hspace"> </span><span class="RktSym">names</span><span class="hspace"> </span><span class="RktSym">ll</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><spa
|
||
|
function takes two arguments, both lists of <span class="RktVal">'</span><span class="RktVal">a</span>, <span class="RktVal">'</span><span class="RktVal">c</span>,
|
||
|
<span class="RktVal">'</span><span class="RktVal">g</span>, and <span class="RktVal">'</span><span class="RktVal">t</span>, symbols that occur in DNA descriptions. The
|
||
|
first list is called a pattern, the second one a search string. The
|
||
|
function returns <span class="RktVal">#true</span> if the pattern is identical to the initial
|
||
|
part of the search string; otherwise it returns <span class="RktVal">#false</span>.</p><p>Also design <span class="RktSym">DNAdelta</span>. This function is like <span class="RktSym">DNAprefix</span> but
|
||
|
returns the first item in the search string beyond the pattern. If the
|
||
|
lists are identical and there is no DNA letter beyond the pattern, the
|
||
|
function signals an error. If the pattern does not match the beginning of
|
||
|
the search string, it returns <span class="RktVal">#false</span>. The function must
|
||
|
not traverse either of the lists more than once.</p><p>Can <span class="RktSym">DNAprefix</span> or <span class="RktSym">DNAdelta</span> be simplified? <a href="part_four.html#%28counter._%28exercise._ex~3adna-prefix%29%29" class="ex-end" data-pltdoc="x"></a></p><p><div class="SIntrapara"><a name="(counter._(exercise._ex~3atest-compare))"></a><span style="font-weight: bold">Exercise</span> 401. Design <span class="RktSym">sexp=?</span>, a function that
|
||
|
determines whether two S-expressions are equal. For convenience,
|
||
|
here is the data definition in condensed form:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">An </span><span style="font-style: italic">S-expr</span><span class="RktCmt"> (S-expression) is one of: </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">–</span><span class="RktCmt"> </span><a href="part_four.html#%28tech._atom%29" class="techoutside" data-pltdoc="x"><span class="techinside">Atom</span></a></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">–</span><span class="RktCmt"> [</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> </span><a href="part_four.html#%28tech._s._expr%29" class="techoutside" data-pltdoc="x"><span class="techinside">S-expr</span></a><span class="RktCmt">]</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">An </span><span style="font-style: italic">Atom</span><span class="RktCmt"> is one of: </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">–</span><span class="RktCmt"> </span><a href="part_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">–</span><span class="RktCmt"> </span><a href="part_one.html#%28tech._string%29" class="techoutside" data-pltdoc="x"><span class="techinside">String</span></a></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">–</span><span class="RktCmt"> </span><a href="i2-3.html#%28tech._symbol%29" class="techoutside" data-pltdoc="x"><span class="techinside">Symbol</span></a><span class="RktCmt"> </span></td></tr></table></blockquote></div></p><p>Whenever you use <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._check-expect%29%29" class="RktStxLink" data-pltdoc="x">check-expect</a></span>, it uses a function like
|
||
|
<span class="RktSym">sexp=?</span> to check whether the two arbitrary values are equal. If
|
||
|
not, the check fails and <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._check-expect%29%29" class="RktStxLink" data-pltdoc="x">check-expect</a></span> reports it as such. <a href="part_four.html#%28counter._%28exercise._ex~3atest-compare%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._(exercise._ex~3absl-var-eval-atomic))"></a><span style="font-weight: bold">Exercise</span> 402. Reread <a href="part_four.html#%28counter._%28exercise._ex~3absl-var-eval%29%29" data-pltdoc="x">exercise 354</a>.
|
||
|
Explain the reasoning behind our hint to think of the given
|
||
|
expression as an atomic value at first. <a href="part_four.html#%28counter._%28exercise._ex~3absl-var-eval-atomic%29%29" class="ex-end" data-pltdoc="x"></a></p><h4>23.7<tt> </tt><a name="(part._db._sec~3aproj-db)"></a>Project: Database</h4><p>Many software applications use a database to keep track of data. Roughly
|
||
|
speaking, a database is a table that comes with an explicitly stated
|
||
|
organization rule. The former is the <span style="font-style: italic">content</span>; the latter
|
||
|
is<span class="refelem"><span class="refcolumn"><span class="refcontent">This section pulls together knowledge from all four parts
|
||
|
of the book.</span></span></span> called a <span style="font-style: italic">schema</span>. <a href="part_four.html#%28counter._db._%28figure._fig~3adb-tables%29%29" data-pltdoc="x">Figure <span class="FigureRef">137</span></a> shows
|
||
|
two examples. Each table consists of two parts: the schema above the line
|
||
|
and the content below.</p><p><div class="SIntrapara">Let’s focus on the table on the left. It has three columns and four
|
||
|
rows. Each column comes with a two-part rule:
|
||
|
</div><div class="SIntrapara"><ol><li><p>the rule in the left-most column says that the label of the column
|
||
|
is “Name” and that every piece of data in this column is a <a href="part_one.html#%28tech._string%29" class="techoutside" data-pltdoc="x"><span class="techinside">String</span></a>;</p></li><li><p>the middle column is labeled “Age” and contains <a href="part_one.html#%28tech._integer%29" class="techoutside" data-pltdoc="x"><span class="techinside">Integer</span></a>s; and</p></li><li><p>the label of the right-most one is “Present”; its values are
|
||
|
<a href="part_one.html#%28tech._boolean%29" class="techoutside" data-pltdoc="x"><span class="techinside">Boolean</span></a>.</p></li></ol></div><div class="SIntrapara">Stop! Explain the table on the right in the same way.</div></p><blockquote class="Figure"><blockquote class="Centerfigure"><blockquote class="FigureInside"><blockquote class="SVInsetFlow"><table cellspacing="0" cellpadding="0" style="border-collapse: collapse;"><tr><td valign="top"><table cellspacing="0" cellpadding="0" style="border-collapse: collapse;"><tr><td align="left"><p>Name</p></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><p>Age</p></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><p>Present</p></td></tr><tr><td align="left" style="border-bottom: 1px solid black;"><p><a href="part_one.html#%28tech._string%29" class="techoutside" data-pltdoc="x"><span class="techinside">String</span></a></p></td><td align="left" style="border-bottom: 1px solid black;"><p><span class="hspace"> </span></p></td><td align="left" style="border-bottom: 1px solid black;"><p><a href="part_one.html#%28tech._integer%29" class="techoutside" data-pltdoc="x"><span class="techinside">Integer</span></a></p></td><td align="left" style="border-bottom: 1px solid black;"><p><span class="hspace"> </span></p></td><td align="left" style="border-bottom: 1px solid black;"><p><a href="part_one.html#%28tech._boolean%29" class="techoutside" data-pltdoc="x"><span class="techinside">Boolean</span></a></p></td></tr><tr><td align="left"><p><span class="RktVal">"Alice"</span></p></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><p><span class="RktVal">35</span></p></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><p><span class="RktVal">#true</span></p></td></tr><tr><td align="left"><p><span class="RktVal">"Bob"</span></p></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><p><span class="RktVal">25</span></p></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><p><span class="RktVal">#false</span></p></td></tr><tr><td align="left"><p><span class="RktVal">"Carol"</span></p></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><p><span class="RktVal">30</span></p></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><p><span class="RktVal">#true</span></p></td></tr><tr><td align="left"><p><span class="RktVal">"Dave"</span></p></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><p><span class="RktVal">32</span></p></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><p><span class="RktVal">#false</span></p></td></tr></table></td><td valign="top"><p><span class="hspace"> </span></p></td><td valign="top" style="border-right: 1px solid black;"><p><span class="hspace"> </span></p></td><td valign="top" style="border-right: 1px solid black;"><p><span class="hspace"> </span></p></td><td valign="top"><table cellspacing="0" cellpadding="0" style="border-collapse: collapse;"><tr><td align="left"><p>Present</p></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><p>Description</p></td></tr><tr><td align="left" style="border-bottom: 1px solid black;"><p><a href="part_one.html#%28tech._boolean%29" class="techoutside" data-pltdoc="x"><span class="techinside">Boolean</span></a></p></td><td align="left" style="border-bottom: 1px solid black;"><p><span class="hspace"> </span></p></td><td align="left" style="border-bottom: 1px solid black;"><p><a href="p
|
||
|
schema introduces terminology to refer to columns of a relation and to
|
||
|
individual cells in a row. Each row relates a fixed number of values; the
|
||
|
collection of all rows makes up the entire relation. In this terminology,
|
||
|
the first row of the left table in <a href="part_four.html#%28counter._db._%28figure._fig~3adb-tables%29%29" data-pltdoc="x">figure <span class="FigureRef">137</span></a> relates
|
||
|
<span class="RktVal">"Alice"</span> to <span class="RktVal">35</span> and <span class="RktVal">#true</span>. Furthermore, the first
|
||
|
cell of a row is called the “Name” cell, the second the “Age” cell,
|
||
|
and the third one the “Present” cell.</p><p><div class="SIntrapara">In this section, we represent databases via structures and lists:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define-struct%29%29" class="RktStxLink" data-pltdoc="x">define-struct</a></span><span class="hspace"> </span><span class="RktSym">db</span><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym">schema</span><span class="hspace"> </span><span class="RktSym">content</span><span class="RktPn">]</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">A </span><a name="(tech._db._db)"></a><span style="font-style: italic">DB</span><span class="RktCmt"> is a structure: </span><span class="RktPn">(</span><span class="RktSym">make-db</span><span class="stt"> </span><a href="part_four.html#%28tech._db._schema%29" class="techoutside" data-pltdoc="x"><span class="techinside">Schema</span></a><span class="stt"> </span><a href="part_four.html#%28tech._db._content%29" class="techoutside" data-pltdoc="x"><span class="techinside">Content</span></a><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">A </span><a name="(tech._db._schema)"></a><span style="font-style: italic">Schema</span><span class="RktCmt"> is a [</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> </span><a href="part_four.html#%28tech._db._spec%29" class="techoutside" data-pltdoc="x"><span class="techinside">Spec</span></a><span class="RktCmt">]</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">A </span><a name="(tech._db._spec)"></a><span style="font-style: italic">Spec</span><span class="RktCmt"> is a [</span><a href="part_three.html#%28tech._sim-dd._list%29" class="techoutside" data-pltdoc="x"><span class="techinside">List</span></a><span class="RktCmt"> </span><a href="part_four.html#%28tech._db._label%29" class="techoutside" data-pltdoc="x"><span class="techinside">Label</span></a><span class="RktCmt"> </span><a href="part_four.html#%28tech._db._predicate%29" class="techoutside" data-pltdoc="x"><span class="techinside">Predicate</span></a><span class="RktCmt">]</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">A </span><a name="(tech._db._label)"></a><span style="font-style: italic">Label</span><span class="RktCmt"> is a </span><a href="part_one.html#%28tech._string%29" class="techoutside" data-pltdoc="x"><span class="techinside">String</span></a></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">A </span><a name="(tech._db._predicate)"></a><span style="font-style: italic">Predicate</span><span class="RktCmt"> is a [</span><a href="part_one.html#%28tech._any%29" class="techoutside" data-pltdoc="x"><span class="techinside">Any</span></a><span class="RktCmt"> -> </span><a href="part_one.html#%28tech._boolean%29" class="techoutside" data-pltdoc="x"><span class="techinside">Boolean</span></a><span class="RktCmt">]</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">A (piece of) </span><a name="(tech._db._content)"></a><span style="font-style: italic">Content</span><span class="RktCmt"> is a [</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> </span><a href="part_four.html#%28tech._db._row%29" class="techoutside" data-pltdoc="x"><span class="techinside">Row</span></a><span class="RktCmt">]</span></td></tr><tr><td><span class="RktCmt">;</s
|
||
|
chosen data representation. Note that the content of the tables already
|
||
|
uses ISL+ data.</div></p><blockquote class="Figure"><blockquote class="Centerfigure"><blockquote class="FigureInside"><blockquote class="SVInsetFlow"><table cellspacing="0" cellpadding="0" style="border-collapse: collapse;"><tr><td valign="top"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">school-schema</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">`</span><span class="RktVal">(</span><span class="RktVal">(</span><span class="RktVal">"Name"</span><span class="hspace"> </span><span class="RktRdr">,</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._string~3f%29%29" class="RktValLink" data-pltdoc="x">string?</a></span><span class="RktVal">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">"Age"</span><span class="hspace"> </span><span class="RktRdr">,</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._integer~3f%29%29" class="RktValLink" data-pltdoc="x">integer?</a></span><span class="RktVal">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">"Present"</span><span class="hspace"> </span><span class="RktRdr">,</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._boolean~3f%29%29" class="RktValLink" data-pltdoc="x">boolean?</a></span><span class="RktVal">)</span><span class="RktVal">)</span><span class="RktPn">)</span></td></tr></table></td><td valign="top"><p><span class="hspace"> </span></p></td><td valign="top" style="border-right: 1px solid black;"><p><span class="hspace"> </span></p></td><td valign="top" style="border-right: 1px solid black;"><p><span class="hspace"> </span></p></td><td valign="top"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">presence-schema</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">`</span><span class="RktVal">(</span><span class="RktVal">(</span><span class="RktVal">"Present"</span><span class="hspace"> </span><span class="RktRdr">,</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._boolean~3f%29%29" class="RktValLink" data-pltdoc="x">boolean?</a></span><span class="RktVal">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">"Description"</span><span class="hspace"> </span><span class="RktRdr">,</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._string~3f%29%29" class="RktValLink" data-pltdoc="x">string?</a></span><span class="RktVal">)</span><span class="RktVal">)</span><span class="RktPn">)</span></td></tr></table></td></tr><tr><td valign="top"><p></p></td><td valign="top"><p><span class="hspace"> </span></p
|
||
|
<a href="part_four.html#%28counter._db._%28figure._fig~3adb-tables%29%29" data-pltdoc="x">figure <span class="FigureRef">137</span></a> as <a href="part_four.html#%28tech._db._db%29" class="techoutside" data-pltdoc="x"><span class="techinside">DB</span></a>s. Its left-hand side represents
|
||
|
the schema, the content, and the database from the left-hand side
|
||
|
table in <a href="part_four.html#%28counter._db._%28figure._fig~3adb-tables%29%29" data-pltdoc="x">figure <span class="FigureRef">137</span></a>; its right part corresponds to the
|
||
|
right-hand side table. For succinctness, the examples use the
|
||
|
<span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._quasiquote%29%29" class="RktStxLink" data-pltdoc="x">quasiquote</a></span> and <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._unquote%29%29" class="RktStxLink" data-pltdoc="x">unquote</a></span> notation. Recall that it allows
|
||
|
the inclusion of a value such as <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._boolean~3f%29%29" class="RktValLink" data-pltdoc="x">boolean?</a></span> in an otherwise
|
||
|
quoted list. If you feel uncomfortable with this
|
||
|
notation, reformulate these examples with <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span>.</p><p><a name="(counter._db._(exercise._ex~3adb-choice-of-rep))"></a><span style="font-weight: bold">Exercise</span> 403. A <a href="part_four.html#%28tech._db._spec%29" class="techoutside" data-pltdoc="x"><span class="techinside">Spec</span></a> combines a <a href="part_four.html#%28tech._db._label%29" class="techoutside" data-pltdoc="x"><span class="techinside">Label</span></a> and
|
||
|
a <a href="part_four.html#%28tech._db._predicate%29" class="techoutside" data-pltdoc="x"><span class="techinside">Predicate</span></a> into a list. While acceptable, this choice violates our
|
||
|
guideline of using a structure type for a fixed number of pieces of
|
||
|
information.</p><p><div class="SIntrapara">Here is an alternative data representation:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define-struct%29%29" class="RktStxLink" data-pltdoc="x">define-struct</a></span><span class="hspace"> </span><span class="RktSym">spec</span><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym">label</span><span class="hspace"> </span><span class="RktSym">predicate</span><span class="RktPn">]</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">Spec is a structure: </span><span class="RktPn">(</span><span class="RktSym">make-spec</span><span class="stt"> </span><a href="part_four.html#%28tech._db._label%29" class="techoutside" data-pltdoc="x"><span class="techinside">Label</span></a><span class="stt"> </span><a href="part_four.html#%28tech._db._predicate%29" class="techoutside" data-pltdoc="x"><span class="techinside">Predicate</span></a><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">Use this alternative definition to represent the databases from
|
||
|
<a href="part_four.html#%28counter._db._%28figure._fig~3adb-tables%29%29" data-pltdoc="x">figure <span class="FigureRef">137</span></a>. <a href="part_four.html#%28counter._db._%28exercise._ex~3adb-choice-of-rep%29%29" class="ex-end" data-pltdoc="x"></a></div></p><p><div class="SIntrapara"><span style="font-weight: bold">Integrity Checking</span> The use of databases critically relies on their
|
||
|
integrity. Here “integrity” refers to the constraints (I1) and (I2) from
|
||
|
the data definition. Checking database integrity is clearly a task for a
|
||
|
function: <a name="(idx._db._(gentag._569._db))"></a>
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_four.html#%28tech._db._db%29" class="techoutside" data-pltdoc="x"><span class="techinside">DB</span></a><span class="RktCmt"> -> </span><a href="part_one.html#%28tech._boolean%29" class="techoutside" data-pltdoc="x"><span class="techinside">Boolean</span></a></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">do all rows in </span><span class="RktSym">db</span><span class="RktCmt"> satisfy (I1) and (I2)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._check-expect%29%29" class="RktStxLink" data-pltdoc="x">check-expect</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">integrity-check</span><span class="hspace"> </span><span class="RktSym">school-db</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">#true</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._check-expect%29%29" class="RktStxLink" data-pltdoc="x">check-expect</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">integrity-check</span><span class="hspace"> </span><span class="RktSym">presence-db</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">#true</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">integrity-check</span><span class="hspace"> </span><span class="RktSym">db</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">#false</span><span class="RktPn">)</span></td></tr></table></blockquote></div></p><p><div class="SIntrapara">The wording of the two constraints suggests that some function has to
|
||
|
produce <span class="RktVal">#true</span> for every row in the content of the given
|
||
|
database. Expressing this idea in code calls for a use of
|
||
|
<span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._andmap%29%29" class="RktValLink" data-pltdoc="x">andmap</a></span> on the content of <span class="RktSym">db</span>:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">integrity-check</span><span class="hspace"> </span><span class="RktSym">db</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._local%29%29" class="RktStxLink" data-pltdoc="x">local</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_four.html#%28tech._db._row%29" class="techoutside" data-pltdoc="x"><span class="techinside">Row</span></a><span class="RktCmt"> -> </span><a href="part_one.html#%28tech._boolean%29" class="techoutside" data-pltdoc="x"><span class="techinside">Boolean</span></a></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">row-integrity-check</span><span class="hspace"> </span><span class="RktSym">row</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._andmap%29%29" class="RktValLink" data-pltdoc="x">andmap</a></span><span class="hspace"> </span><span class="RktSym">row-integrity-check</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">db-content</span><span class="hspace"> </span><span class="RktSym">db</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">Following the <a name="(idx._db._(gentag._570._db))"></a>design recipe for the use of existing abstractions, the
|
||
|
template introduces the auxiliary function via a <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._local%29%29" class="RktStxLink" data-pltdoc="x">local</a></span> definition.</div></p><p><div class="SIntrapara">The design of <span class="RktSym">row-integrity-check</span> starts from this: <a name="(idx._db._(gentag._571._db))"></a>
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_four.html#%28tech._db._row%29" class="techoutside" data-pltdoc="x"><span class="techinside">Row</span></a><span class="RktCmt"> -> </span><a href="part_one.html#%28tech._boolean%29" class="techoutside" data-pltdoc="x"><span class="techinside">Boolean</span></a><span class="RktCmt"> </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">does </span><span class="RktSym">row</span><span class="RktCmt"> satisfy (I1) and (I2) </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">row-integrity-check</span><span class="hspace"> </span><span class="RktSym">row</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">#false</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">As always, the goal of formulating a purpose statement is to understand
|
||
|
the problem. Here it says that the function checks <span style="font-weight: bold">two</span>
|
||
|
conditions. When two tasks are involved, our <a name="(idx._db._(gentag._572._db))"></a>design guidelines call
|
||
|
for functions and the combination of their results:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._and%29%29" class="RktStxLink" data-pltdoc="x">and</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">length-of-row-check</span><span class="hspace"> </span><span class="RktSym">row</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">check-every-cell</span><span class="hspace"> </span><span class="RktSym">row</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">Add these functions to your wish list; their names convey their purpose.</div></p><p><div class="SIntrapara">Before we design these functions, we must contemplate whether we
|
||
|
can compose existing primitive operations to compute the desired
|
||
|
value. For example, we know that <span class="RktPn">(</span><span class="RktSym">length</span><span class="stt"> </span><span class="RktSym">row</span><span class="RktPn">)</span> counts how many
|
||
|
cells are in <span class="RktSym">row</span>. Pushing a bit more in this direction, we
|
||
|
clearly want
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~3d%29%29" class="RktValLink" data-pltdoc="x">=</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">length</span><span class="hspace"> </span><span class="RktSym">row</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">length</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">db-schema</span><span class="hspace"> </span><span class="RktSym">db</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></p></blockquote></div><div class="SIntrapara">This condition checks that the length of <span class="RktSym">row</span> is equal to that
|
||
|
of <span class="RktSym">db</span>’s schema.</div></p><p><div class="SIntrapara">Similarly, <span class="RktSym">check-every-cell</span> calls for checking that some function
|
||
|
produces <span class="RktVal">#true</span> for every cell in the row. Once again, it looks
|
||
|
like <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._andmap%29%29" class="RktValLink" data-pltdoc="x">andmap</a></span> might be called for:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._andmap%29%29" class="RktValLink" data-pltdoc="x">andmap</a></span><span class="hspace"> </span><span class="RktSym">cell-integrity-check</span><span class="hspace"> </span><span class="RktSym">row</span><span class="RktPn">)</span></p></blockquote></div><div class="SIntrapara">The purpose of <span class="RktSym">cell-integrity-check</span> is obviously to check
|
||
|
constraint (I2), that is,
|
||
|
</div><div class="SIntrapara"><blockquote><p>whether “the <span style="font-style: italic">i</span>th <a href="part_four.html#%28tech._db._cell%29" class="techoutside" data-pltdoc="x"><span class="techinside">Cell</span></a> satisfies the <span style="font-style: italic">i</span>th
|
||
|
<a href="part_four.html#%28tech._db._predicate%29" class="techoutside" data-pltdoc="x"><span class="techinside">Predicate</span></a> in <span class="RktSym">db</span>’s schema.”</p></blockquote></div><div class="SIntrapara">And now we are stuck because this purpose statement refers to the relative
|
||
|
position of the given cell in <span class="RktSym">row</span>. The point of <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._andmap%29%29" class="RktValLink" data-pltdoc="x">andmap</a></span>
|
||
|
is, however, to apply <span class="RktSym">cell-integrity-check</span> to every cell <span style="font-weight: bold">uniformly</span>.</div></p><p><div class="SIntrapara">When you are stuck, you must work through examples. For auxiliary or
|
||
|
<span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._local%29%29" class="RktStxLink" data-pltdoc="x">local</a></span> functions, it’s best to derive these examples from the ones
|
||
|
for the main function. The first example for <span class="RktSym">integrity-check</span>
|
||
|
asserts that <span class="RktSym">school-content</span> satisfies the integrity constraints.
|
||
|
Clearly all rows in <span class="RktSym">school-content</span> have the same length as
|
||
|
<span class="RktSym">school-schema</span>. The question is why a row such as
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">"Alice"</span><span class="hspace"> </span><span class="RktVal">35</span><span class="hspace"> </span><span class="RktVal">#true</span><span class="RktPn">)</span></p></blockquote></div><div class="SIntrapara">satisfies the predicates in the corresponding schema:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">"Name"</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._string~3f%29%29" class="RktValLink" data-pltdoc="x">string?</a></span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">"Age"</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._integer~3f%29%29" class="RktValLink" data-pltdoc="x">integer?</a></span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">"Present"</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._boolean~3f%29%29" class="RktValLink" data-pltdoc="x">boolean?</a></span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">The answer is that all three applications of the three predicates to the
|
||
|
respective cells yields true:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._string~3f%29%29" class="RktValLink" data-pltdoc="x">string?</a></span><span class="hspace"> </span><span class="RktVal">"Alice"</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktRes">#true</span></p></td></tr><tr><td><span class="stt">> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._integer~3f%29%29" class="RktValLink" data-pltdoc="x">integer?</a></span><span class="hspace"> </span><span class="RktVal">35</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktRes">#true</span></p></td></tr><tr><td><span class="stt">> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._boolean~3f%29%29" class="RktValLink" data-pltdoc="x">boolean?</a></span><span class="hspace"> </span><span class="RktVal">#true</span><span class="RktPn">)</span></td></tr><tr><td><p><span class="RktRes">#true</span></p></td></tr></table></blockquote></div><div class="SIntrapara">From here, it is just a short step to see that the function must process
|
||
|
these two lists—<wbr></wbr><span class="RktSym">db</span>’s schema and the given row—<wbr></wbr>in parallel.</div></p><p><a name="(counter._db._(exercise._ex~3aandmap2))"></a><span style="font-weight: bold">Exercise</span> 404. Design the function <span class="RktSym">andmap2</span>. It consumes a
|
||
|
function <span class="RktSym">f</span> from two values to <a href="part_one.html#%28tech._boolean%29" class="techoutside" data-pltdoc="x"><span class="techinside">Boolean</span></a> and two equally long
|
||
|
lists. Its result is also a <a href="part_one.html#%28tech._boolean%29" class="techoutside" data-pltdoc="x"><span class="techinside">Boolean</span></a>. Specifically, it applies
|
||
|
<span class="RktSym">f</span> to pairs of corresponding values from the two lists, and if
|
||
|
<span class="RktSym">f</span> always produces <span class="RktVal">#true</span>, <span class="RktSym">andmap2</span> produces
|
||
|
<span class="RktVal">#true</span>, too. Otherwise, <span class="RktSym">andmap2</span> produces
|
||
|
<span class="RktVal">#false</span>. In short, <span class="RktSym">andmap2</span> is like <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._andmap%29%29" class="RktValLink" data-pltdoc="x">andmap</a></span> but for
|
||
|
two lists. <a href="part_four.html#%28counter._db._%28exercise._ex~3aandmap2%29%29" class="ex-end" data-pltdoc="x"></a></p><p>Stop! Solve <a href="part_four.html#%28counter._db._%28exercise._ex~3aandmap2%29%29" data-pltdoc="x">exercise 404</a> before reading on.</p><p><div class="SIntrapara">If we had <span class="RktSym">andmap2</span> in ISL+, checking the second condition on
|
||
|
<span class="RktSym">row</span> would be straightforward:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym">andmap2</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._lambda%29%29" class="RktStxLink" data-pltdoc="x">lambda</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">s</span><span class="hspace"> </span><span class="RktSym">c</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._second%29%29" class="RktValLink" data-pltdoc="x">second</a></span><span class="hspace"> </span><span class="RktSym">s</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">c</span><span class="RktPn">]</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">db-schema</span><span class="hspace"> </span><span class="RktSym">db</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktSym">row</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">The given function consumes a <a href="part_four.html#%28tech._db._spec%29" class="techoutside" data-pltdoc="x"><span class="techinside">Spec</span></a> <span class="RktSym">s</span> from <span class="RktSym">db</span>’s
|
||
|
schema, extracts the predicate in the second position, and applies it to
|
||
|
the given <a href="part_four.html#%28tech._db._cell%29" class="techoutside" data-pltdoc="x"><span class="techinside">Cell</span></a> <span class="RktSym">c</span>. Whatever the predicate returns is the
|
||
|
result of the <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._lambda%29%29" class="RktStxLink" data-pltdoc="x">lambda</a></span> function.</div></p><p>Stop again! Explain <span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._second%29%29" class="RktValLink" data-pltdoc="x">second</a></span><span class="stt"> </span><span class="RktSym">s</span><span class="RktPn">)</span><span class="stt"> </span><span class="RktSym">c</span><span class="RktPn">]</span>.</p><p><div class="SIntrapara">As it turns out, <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._andmap%29%29" class="RktValLink" data-pltdoc="x">andmap</a></span> in ISL+ is already like
|
||
|
<span class="RktSym">andmap2</span>: <a name="(idx._db._(gentag._573._db))"></a>
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">integrity-check</span><span class="hspace"> </span><span class="RktSym">db</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._local%29%29" class="RktStxLink" data-pltdoc="x">local</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_four.html#%28tech._db._row%29" class="techoutside" data-pltdoc="x"><span class="techinside">Row</span></a><span class="RktCmt"> -> </span><a href="part_one.html#%28tech._boolean%29" class="techoutside" data-pltdoc="x"><span class="techinside">Boolean</span></a><span class="RktCmt"> </span></td></tr><tr><td><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">does </span><span class="RktSym">row</span><span class="RktCmt"> satisfy (I1) and (I2) </span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">row-integrity-check</span><span class="hspace"> </span><span class="RktSym">row</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._and%29%29" class="RktStxLink" data-pltdoc="x">and</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~3d%29%29" class="RktValLink" data-pltdoc="x">=</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">length</span><span class="hspace"> </span><span class="RktSym">row</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">length</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">db-schema</span><span class="hspace"> </span><span class="RktSym">db</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._andmap%29%29" class="RktValLink" data-pltdoc="x">andmap</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29.
|
||
|
<span class="RktSym">integrity-check</span> suffers from several problems, some visible, some
|
||
|
invisible. Clearly, the function extracts <span class="RktSym">db</span>’s schema twice. With
|
||
|
the existing <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._local%29%29" class="RktStxLink" data-pltdoc="x">local</a></span> definition it is possible to introduce a
|
||
|
definition and avoid this duplication:</p><p><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">integrity-check.v2</span><span class="hspace"> </span><span class="RktSym">db</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._local%29%29" class="RktStxLink" data-pltdoc="x">local</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">schema</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">db-schema</span><span class="hspace"> </span><span class="RktSym">db</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_four.html#%28tech._db._row%29" class="techoutside" data-pltdoc="x"><span class="techinside">Row</span></a><span class="RktCmt"> -> </span><a href="part_one.html#%28tech._boolean%29" class="techoutside" data-pltdoc="x"><span class="techinside">Boolean</span></a><span class="RktCmt"> </span></td></tr><tr><td><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">does </span><span class="RktSym">row</span><span class="RktCmt"> satisfy (I1) and (I2) </span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">row-integrity-check</span><span class="hspace"> </span><span class="RktSym">row</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._and%29%29" class="RktStxLink" data-pltdoc="x">and</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~3d%29%29" class="RktValLink" data-pltdoc="x">=</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">length</span><span class="hspace"> </span><span class="RktSym">row</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">length</span><span class="hspace"> </span><span class="RktSym">schema</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="h
|
||
|
expression may shorten the time needed to run the integrity check. Like
|
||
|
the definition of <span class="RktSym">inf</span> in <a href="part_three.html#%28counter._%28figure._fig~3alocal-performance%29%29" data-pltdoc="x">figure <span class="FigureRef">100</span></a>, the
|
||
|
original version of <span class="RktSym">integrity-check</span> extracts the schema from
|
||
|
<span class="RktSym">db</span> for every single row, even though it obviously stays
|
||
|
the same.</div></p><p><div class="SIntrapara"><a name="(idx._db._(gentag._574._db))"></a>
|
||
|
</div><div class="SIntrapara"><blockquote class="Figure"><blockquote class="Centerfigure"><blockquote class="FigureInside"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">integrity-check.v3</span><span class="hspace"> </span><span class="RktSym">db</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._local%29%29" class="RktStxLink" data-pltdoc="x">local</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">schema</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">db-schema</span><span class="hspace"> </span><span class="RktSym">db</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">content</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">db-content</span><span class="hspace"> </span><span class="RktSym">db</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">width</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">length</span><span class="hspace"> </span><span class="RktSym">schema</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_four.html#%28tech._db._row%29" class="techoutside" data-pltdoc="x"><span class="techinside">Row</span></a><span class="RktCmt"> -> </span><a href="part_one.html#%28tech._boolean%29" class="techoutside" data-pltdoc="x"><span class="techinside">Boolean</span></a><span class="RktCmt"> </span></td></tr><tr><td><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">does </span><span class="RktSym">row</span><span class="RktCmt"> satisfy (I1) and (I2) </span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">row-integrity-check</span><span class="hspace"> </span><span cl
|
||
|
In a similar vein, the <span class="RktSym">row-integrity-check</span> function determines the
|
||
|
length of <span class="RktSym">db</span>’s schema every single time it is called. The result
|
||
|
is always the same. Hence, if we are interested in improving the
|
||
|
performance of this function, we can use a <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._local%29%29" class="RktStxLink" data-pltdoc="x">local</a></span> definition to
|
||
|
name the <span class="RktSym">width</span> of the database content once and for
|
||
|
all. <a href="part_four.html#%28counter._db._%28figure._fig~3ahoisted%29%29" data-pltdoc="x">Figure <span class="FigureRef">139</span></a> displays the result of hoisting
|
||
|
<span class="RktPn">(</span><span class="RktSym">length</span><span class="stt"> </span><span class="RktSym">schema</span><span class="RktPn">)</span> out of the <span class="RktSym">row-integrity-check</span>. For
|
||
|
readability, this final definition also names the <span class="RktSym">content</span> field
|
||
|
of <span class="RktSym">db</span>. <span style="font-weight: bold">End</span></p><p><span style="font-weight: bold">Projections and Selections</span> Programs need to extract data from
|
||
|
databases. One kind of extraction is to <span style="font-style: italic">select</span> content, which is
|
||
|
explained in <a href="part_two.html#%28part._itunes-data._sec~3aitunes%29" data-pltdoc="x">Real-World Data: iTunes</a>. The other
|
||
|
kind of extraction produces a reduced database; it is dubbed
|
||
|
<span style="font-style: italic">projection</span>. More specifically, a projection constructs a database
|
||
|
by retaining only certain columns from a given database.</p><p><div class="SIntrapara">The description of a projection suggests the following: <a name="(idx._db._(gentag._575._db))"></a>
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_four.html#%28tech._db._db%29" class="techoutside" data-pltdoc="x"><span class="techinside">DB</span></a><span class="RktCmt"> [</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> </span><a href="part_four.html#%28tech._db._label%29" class="techoutside" data-pltdoc="x"><span class="techinside">Label</span></a><span class="RktCmt">] -> </span><a href="part_four.html#%28tech._db._db%29" class="techoutside" data-pltdoc="x"><span class="techinside">DB</span></a></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">retains a column from </span><span class="RktSym">db</span><span class="RktCmt"> if its label is in </span><span class="RktSym">labels</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">project</span><span class="hspace"> </span><span class="RktSym">db</span><span class="hspace"> </span><span class="RktSym">labels</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">make-db</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">Given the complexity of a projection, it is best to work through an
|
||
|
example first. Say we wish to eliminate the age column from
|
||
|
the database on the left in <a href="part_four.html#%28counter._db._%28figure._fig~3adb-tables%29%29" data-pltdoc="x">figure <span class="FigureRef">137</span></a>. Here is what this
|
||
|
transformation looks like in terms of tables:
|
||
|
</div><div class="SIntrapara"><blockquote class="SVInsetFlow"><table cellspacing="0" cellpadding="0" style="border-collapse: collapse;"><tr><td align="center" style="border-bottom: 1px solid black;"><p>the original database</p></td><td align="center" style="border-bottom: 1px solid black;"><p><span class="hspace"> </span></p></td><td align="center" style="border-bottom: 1px solid black;"><p>... eliminating the “Age” column</p></td></tr><tr><td align="center"><table cellspacing="0" cellpadding="0" style="border-collapse: collapse;"><tr><td align="left"><p>Name</p></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><p>Age</p></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><p>Present</p></td></tr><tr><td align="left" style="border-bottom: 1px solid black;"><p><a href="part_one.html#%28tech._string%29" class="techoutside" data-pltdoc="x"><span class="techinside">String</span></a></p></td><td align="left" style="border-bottom: 1px solid black;"><p><span class="hspace"> </span></p></td><td align="left" style="border-bottom: 1px solid black;"><p><a href="part_one.html#%28tech._integer%29" class="techoutside" data-pltdoc="x"><span class="techinside">Integer</span></a></p></td><td align="left" style="border-bottom: 1px solid black;"><p><span class="hspace"> </span></p></td><td align="left" style="border-bottom: 1px solid black;"><p><a href="part_one.html#%28tech._boolean%29" class="techoutside" data-pltdoc="x"><span class="techinside">Boolean</span></a></p></td></tr><tr><td align="left"><p><span class="RktVal">"Alice"</span></p></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><p><span class="RktVal">35</span></p></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><p><span class="RktVal">#true</span></p></td></tr><tr><td align="left"><p><span class="RktVal">"Bob"</span></p></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><p><span class="RktVal">25</span></p></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><p><span class="RktVal">#false</span></p></td></tr><tr><td align="left"><p><span class="RktVal">"Carol"</span></p></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><p><span class="RktVal">30</span></p></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><p><span class="RktVal">#true</span></p></td></tr><tr><td align="left"><p><span class="RktVal">"Dave"</span></p></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><p><span class="RktVal">32</span></p></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><p><span class="RktVal">#false</span></p></td></tr></table></td><td align="center"><p><span class="hspace"> </span></p></td><td align="center"><table cellspacing="0" cellpadding="0" style="border-collapse: collapse;"><tr><td align="left"><p>Name</p></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><p>Present</p></td></tr><tr><td align="left" style="border-bottom: 1px solid black;"><p><a href="part_one.html#%28tech._string%29" class="techoutside" data-pltdoc="x"><span class="techinside">String</span></a></p></td><td align="left" style="border-bottom: 1px solid black;"><p><span class="hspace"> </span></p></td><td align="left" style="border-bottom: 1px solid black;"><p><a href="part_one.html#%28tech._boolean%29" class="techoutside" data-pltdoc="x"><span class="techinside">Boolean</span></a></p></td></tr><tr><td align="left"><p><span class="RktVal">"Alice"</span></p></td><td align="left
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">projected-content</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">`</span><span class="RktVal">(</span><span class="RktVal">(</span><span class="RktVal">"Alice"</span><span class="hspace"> </span><span class="RktVal">#true</span><span class="RktVal">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">"Bob"</span><span class="hspace"> </span><span class="RktVal">#false</span><span class="RktVal">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">"Carol"</span><span class="hspace"> </span><span class="RktVal">#true</span><span class="RktVal">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">"Dave"</span><span class="hspace"> </span><span class="RktVal">#false</span><span class="RktVal">)</span><span class="RktVal">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">projected-schema</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">`</span><span class="RktVal">(</span><span class="RktVal">(</span><span class="RktVal">"Name"</span><span class="hspace"> </span><span class="RktRdr">,</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._string~3f%29%29" class="RktValLink" data-pltdoc="x">string?</a></span><span class="RktVal">)</span><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">"Present"</span><span class="hspace"> </span><span class="RktRdr">,</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._boolean~3f%29%29" class="RktValLink" data-pltdoc="x">boolean?</a></span><span class="RktVal">)</span><span class="RktVal">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">projected-db</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">make-db</span><span class="hspace"> </span><span class="RktSym">projected-schema</span><span class="hspace"> </span><span class="RktSym">projected-content</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt"> Stop! Read this test carefully. What</span><span class="RktCmt">'</span><span class="RktCmt">s wrong?</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._check-expect%29%29" class="RktStxLink" data-pltdoc="x">chec
|
||
|
</div><div class="SIntrapara"><blockquote class="Herefigure"><blockquote class="Centerfigure"><blockquote class="FigureInside"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">project</span><span class="hspace"> </span><span class="RktSym">db</span><span class="hspace"> </span><span class="RktSym">labels</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._local%29%29" class="RktStxLink" data-pltdoc="x">local</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">schema</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">db-schema</span><span class="hspace"> </span><span class="RktSym">db</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">content</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">db-content</span><span class="hspace"> </span><span class="RktSym">db</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_four.html#%28tech._db._spec%29" class="techoutside" data-pltdoc="x"><span class="techinside">Spec</span></a><span class="RktCmt"> -> </span><a href="part_one.html#%28tech._boolean%29" class="techoutside" data-pltdoc="x"><span class="techinside">Boolean</span></a></td></tr><tr><td><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">does this spec belong to the new schema</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">keep?</span><span class="hspace"> </span><span class="RktSym">c</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_four.html#%28tech._db._row%29" class="techoutside" data-pltdoc="x"><span class="techinside">Row</span></a><span class="RktCmt"> -> </span
|
||
|
</div><div class="SIntrapara"><blockquote class="SCentered"><p><span class="stt">first argument of equality cannot be a function</span></p></blockquote></div><div class="SIntrapara">before DrRacket can even figure out whether the test succeeds. Recall from
|
||
|
<a href="part_three.html#%28part._sec~3afunctions-as-values%29" data-pltdoc="x">Functions Are Values</a> that
|
||
|
functions are infinitely large objects and it is impossible to ensure that
|
||
|
two functions always produce the same result when applied to the same
|
||
|
arguments. We therefore weaken the test case:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._check-expect%29%29" class="RktStxLink" data-pltdoc="x">check-expect</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">db-content</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">project</span><span class="hspace"> </span><span class="RktSym">school-db</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">"Name"</span><span class="hspace"> </span><span class="RktVal">"Present"</span><span class="RktVal">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktSym">projected-content</span><span class="RktPn">)</span></td></tr></table></blockquote></div></p><p>For the template, we again reuse existing abstractions; see
|
||
|
<a href="part_four.html#%28counter._db._%28figure._fig~3aproject-template%29%29" data-pltdoc="x">figure <span class="FigureRef">140</span></a>. The <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._local%29%29" class="RktStxLink" data-pltdoc="x">local</a></span> expression defines
|
||
|
two functions: one for use with <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._filter%29%29" class="RktValLink" data-pltdoc="x">filter</a></span> for narrowing down the
|
||
|
schema of the given database and the other for use with <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._map%29%29" class="RktValLink" data-pltdoc="x">map</a></span> for
|
||
|
thinning out the content. In addition, the function again extracts and
|
||
|
names the schema and the content from the given database.</p><p>Before we turn to the wish list, let’s step back and study
|
||
|
the decision to go with two reuses of existing abstraction. The signature
|
||
|
tells us that the function consumes a structure and produces an element of
|
||
|
<a href="part_four.html#%28tech._db._db%29" class="techoutside" data-pltdoc="x"><span class="techinside">DB</span></a>, so</p><p><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._local%29%29" class="RktStxLink" data-pltdoc="x">local</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">schema</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">db-schema</span><span class="hspace"> </span><span class="RktSym">db</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">content</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">db-content</span><span class="hspace"> </span><span class="RktSym">db</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">make-db</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="hspace"> </span><span class="RktSym">schema</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="hspace"> </span><span class="RktSym">content</span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">is clearly called for. It is also straightforward to see that the new
|
||
|
schema is created from the old schema and the new content from the old
|
||
|
content. Furthermore, the purpose statement of <span class="RktSym">project</span> calls for
|
||
|
the retention of only those labels that are mentioned in the second
|
||
|
argument. Hence, the <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._filter%29%29" class="RktValLink" data-pltdoc="x">filter</a></span> function correctly narrows down the
|
||
|
given <span class="RktSym">schema</span>. In contrast, the rows per se stay except that each
|
||
|
of them loses some cells. Thus, <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._map%29%29" class="RktValLink" data-pltdoc="x">map</a></span> is the proper way of
|
||
|
processing <span class="RktSym">content</span>.</div></p><p><div class="SIntrapara">Now we can turn to the design of the two auxiliary functions. The
|
||
|
design of <span class="RktSym">keep?</span> is straightforward. Here is the complete
|
||
|
definition: <a name="(idx._db._(gentag._577._db))"></a>
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_four.html#%28tech._db._spec%29" class="techoutside" data-pltdoc="x"><span class="techinside">Spec</span></a><span class="RktCmt"> -> </span><a href="part_one.html#%28tech._boolean%29" class="techoutside" data-pltdoc="x"><span class="techinside">Boolean</span></a></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">does this spec belong to the new schema</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">keep?</span><span class="hspace"> </span><span class="RktSym">c</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._member~3f%29%29" class="RktValLink" data-pltdoc="x">member?</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._first%29%29" class="RktValLink" data-pltdoc="x">first</a></span><span class="hspace"> </span><span class="RktSym">c</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">labels</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">The function is applied to a <a href="part_four.html#%28tech._db._spec%29" class="techoutside" data-pltdoc="x"><span class="techinside">Spec</span></a>, which combines a <a href="part_four.html#%28tech._db._label%29" class="techoutside" data-pltdoc="x"><span class="techinside">Label</span></a>
|
||
|
and a <a href="part_four.html#%28tech._db._predicate%29" class="techoutside" data-pltdoc="x"><span class="techinside">Predicate</span></a> in a list. If the former belongs to <span class="RktSym">labels</span>,
|
||
|
the given <a href="part_four.html#%28tech._db._spec%29" class="techoutside" data-pltdoc="x"><span class="techinside">Spec</span></a> is kept.</div></p><p><div class="SIntrapara">For the design of <span class="RktSym">row-project</span>, the goal is to keep those
|
||
|
<a href="part_four.html#%28tech._db._cell%29" class="techoutside" data-pltdoc="x"><span class="techinside">Cell</span></a>s in each <a href="part_four.html#%28tech._db._row%29" class="techoutside" data-pltdoc="x"><span class="techinside">Row</span></a> of <span class="RktSym">content</span> whose name is a member
|
||
|
of the given <span class="RktSym">labels</span>. Let’s work through the above example.
|
||
|
The four rows are:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">"Alice"</span><span class="hspace"> </span><span class="RktVal">35</span><span class="hspace"> </span><span class="RktVal">#true</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">"Bob"</span><span class="hspace"> </span><span class="RktVal">25</span><span class="hspace"> </span><span class="RktVal">#false</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">"Carol"</span><span class="hspace"> </span><span class="RktVal">30</span><span class="hspace"> </span><span class="RktVal">#true</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">"Dave"</span><span class="hspace"> </span><span class="RktVal">32</span><span class="hspace"> </span><span class="RktVal">#false</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">Each of these rows is as long as <span class="RktSym">school-schema</span>:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">"Name"</span><span class="hspace"> </span><span class="RktVal">"Age"</span><span class="hspace"> </span><span class="RktVal">"Present"</span><span class="RktPn">)</span></p></blockquote></div><div class="SIntrapara">The names in the schema determine the names of the cells in the given
|
||
|
rows. Hence, <span class="RktSym">row-project</span> must keep the first and third cell of
|
||
|
each row because it is their names that are in the given <span class="RktSym">labels</span>.</div></p><p><div class="SIntrapara">Since <a href="part_four.html#%28tech._db._row%29" class="techoutside" data-pltdoc="x"><span class="techinside">Row</span></a> is defined recursively, this matching process between the
|
||
|
content of the <a href="part_four.html#%28tech._db._cell%29" class="techoutside" data-pltdoc="x"><span class="techinside">Cell</span></a>s and their names calls for a recursive helper
|
||
|
function that <span class="RktSym">row-project</span> can apply to the content and the labels
|
||
|
of the cells. Let’s specify it as a wish: <a name="(idx._db._(gentag._578._db))"></a> <a name="(idx._db._(gentag._579._db))"></a>
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_four.html#%28tech._db._row%29" class="techoutside" data-pltdoc="x"><span class="techinside">Row</span></a><span class="RktCmt"> [</span><a href="part_three.html#%28tech._sim-dd._list._of%29" class="techoutside" data-pltdoc="x"><span class="techinside">List-of</span></a><span class="RktCmt"> </span><a href="part_four.html#%28tech._db._label%29" class="techoutside" data-pltdoc="x"><span class="techinside">Label</span></a><span class="RktCmt">] -> </span><a href="part_four.html#%28tech._db._row%29" class="techoutside" data-pltdoc="x"><span class="techinside">Row</span></a></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">retains those cells whose corresponding element </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">in </span><span class="RktSym">names</span><span class="RktCmt"> is also in </span><span class="RktSym">labels</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">row-filter</span><span class="hspace"> </span><span class="RktSym">row</span><span class="hspace"> </span><span class="RktSym">names</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">Using this wish, <span class="RktSym">row-project</span> is a one-liner:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">row-project</span><span class="hspace"> </span><span class="RktSym">row</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">row-filter</span><span class="hspace"> </span><span class="RktSym">row</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._map%29%29" class="RktValLink" data-pltdoc="x">map</a></span><span class="hspace"> </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._first%29%29" class="RktValLink" data-pltdoc="x">first</a></span><span class="hspace"> </span><span class="RktSym">schema</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">The <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._map%29%29" class="RktValLink" data-pltdoc="x">map</a></span> expression extracts the names of the cells,
|
||
|
and those names are handed to <span class="RktSym">row-filter</span> to extract the matching
|
||
|
cells.</div></p><p><a name="(counter._db._(exercise._ex~3arow-filter))"></a><span style="font-weight: bold">Exercise</span> 405. Design the function <span class="RktSym">row-filter</span>.
|
||
|
Construct examples for <span class="RktSym">row-filter</span> from the examples for
|
||
|
<span class="RktSym">project</span>.</p><p><span style="font-weight: bold">Assumption</span> The given database passes an integrity check, meaning
|
||
|
each row is as long as the schema and thus its list of names. <a href="part_four.html#%28counter._db._%28exercise._ex~3arow-filter%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a href="part_four.html#%28counter._db._%28figure._fig~3adb-project%29%29" data-pltdoc="x">Figure <span class="FigureRef">141</span></a> puts all the pieces together. The function
|
||
|
<span class="RktSym">project</span> has the suffix <span class="stt">.v1</span> because it calls for some
|
||
|
improvement. The following exercises ask you to implement some of those.</p><p><div class="SIntrapara"><a name="(idx._db._(gentag._580._db))"></a>
|
||
|
</div><div class="SIntrapara"><blockquote class="Figure"><blockquote class="Centerfigure"><blockquote class="FigureInside"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">project.v1</span><span class="hspace"> </span><span class="RktSym">db</span><span class="hspace"> </span><span class="RktSym">labels</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._local%29%29" class="RktStxLink" data-pltdoc="x">local</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">schema</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">db-schema</span><span class="hspace"> </span><span class="RktSym">db</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">content</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">db-content</span><span class="hspace"> </span><span class="RktSym">db</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_four.html#%28tech._db._spec%29" class="techoutside" data-pltdoc="x"><span class="techinside">Spec</span></a><span class="RktCmt"> -> </span><a href="part_one.html#%28tech._boolean%29" class="techoutside" data-pltdoc="x"><span class="techinside">Boolean</span></a></td></tr><tr><td><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">does this column belong to the new schema</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">keep?</span><span class="hspace"> </span><span class="RktSym">c</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._member~3f%29%29" class="RktValLink" data-pltdoc="x">member?</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lamb
|
||
|
recomputes the labels for every row of the database’s content. Does the
|
||
|
result differ from function call to function call? If not, hoist the expression. <a href="part_four.html#%28counter._db._%28exercise._ex~3arow-project-hoist%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._db._(exercise._ex~3arow-filter/fold))"></a><span style="font-weight: bold">Exercise</span> 407. Redesign <span class="RktSym">row-filter</span> using
|
||
|
<span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._foldr%29%29" class="RktValLink" data-pltdoc="x">foldr</a></span>. Once you have done so, you may merge <span class="RktSym">row-project</span>
|
||
|
and <span class="RktSym">row-filter</span> into a single function. <span style="font-weight: bold">Hint</span> The
|
||
|
<span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._foldr%29%29" class="RktValLink" data-pltdoc="x">foldr</a></span> function in ISL+ may consume two lists and process them
|
||
|
in parallel. <a href="part_four.html#%28counter._db._%28exercise._ex~3arow-filter%2Ffold%29%29" class="ex-end" data-pltdoc="x"></a></p><p>The final observation is that <span class="RktSym">row-project</span> checks the membership of
|
||
|
a label in <span class="RktSym">labels</span> for every single cell. For the cells of the
|
||
|
same column in different rows, the result is going to be the same. Hence
|
||
|
it also makes sense to hoist this computation out of the function.</p><p><div class="SIntrapara">This form of hoisting is somewhat more difficult than plain expression
|
||
|
hoisting. We basically wish to pre-compute the result of
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._member~3f%29%29" class="RktValLink" data-pltdoc="x">member?</a></span><span class="hspace"> </span><span class="RktSym">label</span><span class="hspace"> </span><span class="RktSym">labels</span><span class="RktPn">)</span></p></blockquote></div><div class="SIntrapara">for all rows and pass the results into the function instead of the list of
|
||
|
labels. That is, we replace the list of labels with a list of <a href="part_one.html#%28tech._boolean%29" class="techoutside" data-pltdoc="x"><span class="techinside">Boolean</span></a>s
|
||
|
that indicate whether the cell in the corresponding position is to be
|
||
|
kept. Fortunately, computing those <a href="part_one.html#%28tech._boolean%29" class="techoutside" data-pltdoc="x"><span class="techinside">Boolean</span></a>s is just another application of
|
||
|
<span class="RktSym">keep?</span> on the schema:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._map%29%29" class="RktValLink" data-pltdoc="x">map</a></span><span class="hspace"> </span><span class="RktSym">keep?</span><span class="hspace"> </span><span class="RktSym">schema</span><span class="RktPn">)</span></p></blockquote></div><div class="SIntrapara">Instead of keeping some <a href="part_four.html#%28tech._db._spec%29" class="techoutside" data-pltdoc="x"><span class="techinside">Spec</span></a>s from the given <span class="RktSym">schema</span> and
|
||
|
throwing away the others, this expression just collects the decisions.</div></p><p><div class="SIntrapara"><a name="(idx._db._(gentag._581._db))"></a>
|
||
|
</div><div class="SIntrapara"><blockquote class="Figure"><blockquote class="Centerfigure"><blockquote class="FigureInside"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">project</span><span class="hspace"> </span><span class="RktSym">db</span><span class="hspace"> </span><span class="RktSym">labels</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._local%29%29" class="RktStxLink" data-pltdoc="x">local</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">schema</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">db-schema</span><span class="hspace"> </span><span class="RktSym">db</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">content</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">db-content</span><span class="hspace"> </span><span class="RktSym">db</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_four.html#%28tech._db._spec%29" class="techoutside" data-pltdoc="x"><span class="techinside">Spec</span></a><span class="RktCmt"> -> </span><a href="part_one.html#%28tech._boolean%29" class="techoutside" data-pltdoc="x"><span class="techinside">Boolean</span></a></td></tr><tr><td><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">does this column belong to the new schema</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">keep?</span><span class="hspace"> </span><span class="RktSym">c</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._member~3f%29%29" class="RktValLink" data-pltdoc="x">member?</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda.
|
||
|
integrates the solutions for the preceding exercises. It also uses
|
||
|
<span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._local%29%29" class="RktStxLink" data-pltdoc="x">local</a></span> to extract and name <span class="RktSym">schema</span> and <span class="RktSym">content</span>,
|
||
|
plus <span class="RktSym">keep?</span> for checking whether the label in some <a href="part_four.html#%28tech._db._spec%29" class="techoutside" data-pltdoc="x"><span class="techinside">Spec</span></a> is
|
||
|
worth keeping. The remaining two definitions introduce <span class="RktSym">mask</span>, which
|
||
|
stands for the list of <a href="part_one.html#%28tech._boolean%29" class="techoutside" data-pltdoc="x"><span class="techinside">Boolean</span></a>s discussed above, and the revised version of
|
||
|
<span class="RktSym">row-project</span>. The latter uses <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._foldr%29%29" class="RktValLink" data-pltdoc="x">foldr</a></span> to process the given
|
||
|
<span class="RktSym">row</span> and <span class="RktSym">mask</span> in parallel.</p><p>Compare this revised definition of <span class="RktSym">project</span> with <span class="RktSym">project.v1</span>
|
||
|
in <a href="part_four.html#%28counter._db._%28figure._fig~3adb-project%29%29" data-pltdoc="x">figure <span class="FigureRef">141</span></a>. The final definition is both simpler and
|
||
|
faster than the original version. Systematic design combined with careful
|
||
|
revisions pays off; <a name="(idx._db._(gentag._582._db))"></a>test suites ensure that revisions don’t mess up the
|
||
|
functionality of the program.</p><p><a name="(counter._db._(exercise._ex~3adb-select))"></a><span style="font-weight: bold">Exercise</span> 408. Design the function <span class="RktSym">select</span>. It consumes a
|
||
|
database, a list of labels, and a predicate on rows. The result is a list of
|
||
|
rows that satisfy the given predicate, projected down to the given set of
|
||
|
labels. <a href="part_four.html#%28counter._db._%28exercise._ex~3adb-select%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._db._(exercise._ex~3adb-reorder))"></a><span style="font-weight: bold">Exercise</span> 409. Design <span class="RktSym">reorder</span>. The function consumes a
|
||
|
database <span class="RktSym">db</span> and list <span class="RktSym">lol</span> of <a href="part_four.html#%28tech._db._label%29" class="techoutside" data-pltdoc="x"><span class="techinside">Label</span></a>s. It produces a
|
||
|
database like <span class="RktSym">db</span> but with its columns reordered according to
|
||
|
<span class="RktSym">lol</span>. <span style="font-weight: bold">Hint</span> Read up on <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._list-ref%29%29" class="RktValLink" data-pltdoc="x">list-ref</a></span>.</p><p>At first assume that <span class="RktSym">lol</span> consists exactly of the labels of
|
||
|
<span class="RktSym">db</span>’s columns. Once you have completed the design, study what has
|
||
|
to be changed if <span class="RktSym">lol</span> contains fewer labels than there are columns
|
||
|
and strings that are not labels of a column in <span class="RktSym">db</span>. <a href="part_four.html#%28counter._db._%28exercise._ex~3adb-reorder%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._db._(exercise._ex~3adb-union))"></a><span style="font-weight: bold">Exercise</span> 410. Design the function <span class="RktSym">db-union</span>, which
|
||
|
consumes two databases with the exact same schema and produces a new
|
||
|
database with this schema and the joint content of both. The function must
|
||
|
eliminate rows with the exact same content.</p><p>Assume that the schemas agree on the predicates for each column. <a href="part_four.html#%28counter._db._%28exercise._ex~3adb-union%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._db._(exercise._ex~3adb-join))"></a><span style="font-weight: bold">Exercise</span> 411. Design <span class="RktSym">join</span>, a function that consumes two
|
||
|
databases: <span class="RktSym">db-1</span> and <span class="RktSym">db-2</span>. The schema of <span class="RktSym">db-2</span>
|
||
|
starts with the exact same <a href="part_four.html#%28tech._db._spec%29" class="techoutside" data-pltdoc="x"><span class="techinside">Spec</span></a> that the schema of <span class="RktSym">db-1</span>
|
||
|
ends in. The function creates a database from <span class="RktSym">db-1</span> by
|
||
|
replacing the last cell in each row with the <span style="font-style: italic">translation</span> of the cell
|
||
|
in <span class="RktSym">db-2</span>.</p><p><div class="SIntrapara">Here is an example. Take the databases in <a href="part_four.html#%28counter._db._%28figure._fig~3adb-tables%29%29" data-pltdoc="x">figure <span class="FigureRef">137</span></a>. The
|
||
|
two satisfy the assumption of these exercises, that is, the last
|
||
|
<a href="part_four.html#%28tech._db._spec%29" class="techoutside" data-pltdoc="x"><span class="techinside">Spec</span></a> in the schema of the first is equal to the first <a href="part_four.html#%28tech._db._spec%29" class="techoutside" data-pltdoc="x"><span class="techinside">Spec</span></a>
|
||
|
of the second. Hence it is possible to join them:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCentered"><table cellspacing="0" cellpadding="0" style="border-collapse: collapse;"><tr><td align="left"><p>Name</p></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><p>Age</p></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><p>Description</p></td></tr><tr><td align="left" style="border-bottom: 1px solid black;"><p><a href="part_one.html#%28tech._string%29" class="techoutside" data-pltdoc="x"><span class="techinside">String</span></a></p></td><td align="left" style="border-bottom: 1px solid black;"><p><span class="hspace"> </span></p></td><td align="left" style="border-bottom: 1px solid black;"><p><a href="part_one.html#%28tech._integer%29" class="techoutside" data-pltdoc="x"><span class="techinside">Integer</span></a></p></td><td align="left" style="border-bottom: 1px solid black;"><p><span class="hspace"> </span></p></td><td align="left" style="border-bottom: 1px solid black;"><p><a href="part_one.html#%28tech._string%29" class="techoutside" data-pltdoc="x"><span class="techinside">String</span></a></p></td></tr><tr><td align="left"><p><span class="RktVal">"Alice"</span></p></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><p><span class="RktVal">35</span></p></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><p><span class="RktVal">"presence"</span></p></td></tr><tr><td align="left"><p><span class="RktVal">"Bob"</span></p></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><p><span class="RktVal">25</span></p></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><p><span class="RktVal">"absence"</span></p></td></tr><tr><td align="left"><p><span class="RktVal">"Carol"</span></p></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><p><span class="RktVal">30</span></p></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><p><span class="RktVal">"presence"</span></p></td></tr><tr><td align="left"><p><span class="RktVal">"Dave"</span></p></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><p><span class="RktVal">32</span></p></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><p><span class="RktVal">"absence"</span></p></td></tr></table></blockquote></div><div class="SIntrapara">Its translation maps <span class="RktVal">#true</span> to <span class="RktVal">"presence"</span> and
|
||
|
<span class="RktVal">#false</span> to <span class="RktVal">"absence"</span>.</div></p><p><span style="font-weight: bold">Hints</span> (1) In general, the second database may “translate” a cell to
|
||
|
a row of values, not just one value. Modify the example by adding additional terms
|
||
|
to the row for <span class="RktVal">"presence"</span> and <span class="RktVal">"absence"</span>.</p><p><div class="SIntrapara">(2) It may also “translate” a cell to several rows, in which case the
|
||
|
process adds several rows to the new database. Here is a second example, a
|
||
|
slightly different pair of databases from those in
|
||
|
<a href="part_four.html#%28counter._db._%28figure._fig~3adb-tables%29%29" data-pltdoc="x">figure <span class="FigureRef">137</span></a>:
|
||
|
</div><div class="SIntrapara"><blockquote class="SVInsetFlow"><table cellspacing="0" cellpadding="0" style="border-collapse: collapse;"><tr><td><table cellspacing="0" cellpadding="0" style="border-collapse: collapse;"><tr><td align="left"><p>Name</p></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><p>Age</p></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><p>Present</p></td></tr><tr><td align="left" style="border-bottom: 1px solid black;"><p><a href="part_one.html#%28tech._string%29" class="techoutside" data-pltdoc="x"><span class="techinside">String</span></a></p></td><td align="left" style="border-bottom: 1px solid black;"><p><span class="hspace"> </span></p></td><td align="left" style="border-bottom: 1px solid black;"><p><a href="part_one.html#%28tech._integer%29" class="techoutside" data-pltdoc="x"><span class="techinside">Integer</span></a></p></td><td align="left" style="border-bottom: 1px solid black;"><p><span class="hspace"> </span></p></td><td align="left" style="border-bottom: 1px solid black;"><p><a href="part_one.html#%28tech._boolean%29" class="techoutside" data-pltdoc="x"><span class="techinside">Boolean</span></a></p></td></tr><tr><td align="left"><p><span class="RktVal">"Alice"</span></p></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><p><span class="RktVal">35</span></p></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><p><span class="RktVal">#true</span></p></td></tr><tr><td align="left"><p><span class="RktVal">"Bob"</span></p></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><p><span class="RktVal">25</span></p></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><p><span class="RktVal">#false</span></p></td></tr><tr><td align="left"><p><span class="RktVal">"Carol"</span></p></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><p><span class="RktVal">30</span></p></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><p><span class="RktVal">#true</span></p></td></tr><tr><td align="left"><p><span class="RktVal">"Dave"</span></p></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><p><span class="RktVal">32</span></p></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><p><span class="RktVal">#false</span></p></td></tr></table></td><td><p><span class="hspace"> </span></p></td><td style="border-right: 1px solid black;"><p><span class="hspace"> </span></p></td><td style="border-right: 1px solid black;"><p><span class="hspace"> </span></p></td><td><table cellspacing="0" cellpadding="0" style="border-collapse: collapse;"><tr><td align="left"><p>Present</p></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><p>Description</p></td></tr><tr><td align="left" style="border-bottom: 1px solid black;"><p><a href="part_one.html#%28tech._boolean%29" class="techoutside" data-pltdoc="x"><span class="techinside">Boolean</span></a></p></td><td align="left" style="border-bottom: 1px solid black;"><p><span class="hspace"> </span></p></td><td align="left" style="border-bottom: 1px solid black;"><p><a href="part_one.html#%28tech._string%29" class="techoutside" data-pltdoc="x"><span class="techinside">String</span></a></p></td></tr><tr><td align="left"><p><span class="RktVal">#true</span></p></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><p><span class="RktVal">"presence"</span></p></td></tr><tr><td align="left"><p><span class="RktVal">#true<
|
||
|
eight rows:
|
||
|
</div><div class="SIntrapara"><blockquote class="SCentered"><table cellspacing="0" cellpadding="0" style="border-collapse: collapse;"><tr><td align="left"><p>Name</p></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><p>Age</p></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><p>Description</p></td></tr><tr><td align="left" style="border-bottom: 1px solid black;"><p><a href="part_one.html#%28tech._string%29" class="techoutside" data-pltdoc="x"><span class="techinside">String</span></a></p></td><td align="left" style="border-bottom: 1px solid black;"><p><span class="hspace"> </span></p></td><td align="left" style="border-bottom: 1px solid black;"><p><a href="part_one.html#%28tech._integer%29" class="techoutside" data-pltdoc="x"><span class="techinside">Integer</span></a></p></td><td align="left" style="border-bottom: 1px solid black;"><p><span class="hspace"> </span></p></td><td align="left" style="border-bottom: 1px solid black;"><p><a href="part_one.html#%28tech._string%29" class="techoutside" data-pltdoc="x"><span class="techinside">String</span></a></p></td></tr><tr><td align="left"><p><span class="RktVal">"Alice"</span></p></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><p><span class="RktVal">35</span></p></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><p><span class="RktVal">"presence"</span></p></td></tr><tr><td align="left"><p><span class="RktVal">"Alice"</span></p></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><p><span class="RktVal">35</span></p></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><p><span class="RktVal">"here"</span></p></td></tr><tr><td align="left"><p><span class="RktVal">"Bob"</span></p></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><p><span class="RktVal">25</span></p></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><p><span class="RktVal">"absence"</span></p></td></tr><tr><td align="left"><p><span class="RktVal">"Bob"</span></p></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><p><span class="RktVal">25</span></p></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><p><span class="RktVal">"there"</span></p></td></tr><tr><td align="left"><p><span class="RktVal">"Carol"</span></p></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><p><span class="RktVal">30</span></p></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><p><span class="RktVal">"presence"</span></p></td></tr><tr><td align="left"><p><span class="RktVal">"Carol"</span></p></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><p><span class="RktVal">30</span></p></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><p><span class="RktVal">"here"</span></p></td></tr><tr><td align="left"><p><span class="RktVal">"Dave"</span></p></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><p><span class="RktVal">32</span></p></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><p><span class="RktVal">"absence"</span></p></td></tr><tr><td align="left"><p><span class="RktVal">"Dave"</span></p></td><td align="left"><p><span class="hspace"> </span></p></td><td align="left"><p><span class="RktVal">32</span></p></td><td align="left"><p><span class=
|
||
|
assume that a “translation” finds only one row per cell. For the second
|
||
|
one, drop the assumption.</p><p><span style="font-weight: bold">Note on Assumptions</span> This exercise and the entire section mostly rely
|
||
|
on informally stated assumptions about the given databases. Here, the
|
||
|
design of <span class="RktSym">join</span> assumes that “the schema of <span class="RktSym">db-2</span> starts
|
||
|
with the exact same <a href="part_four.html#%28tech._db._spec%29" class="techoutside" data-pltdoc="x"><span class="techinside">Spec</span></a> that the schema of <span class="RktSym">db-1</span> ends
|
||
|
in.” In reality, database functions must be checked functions in the
|
||
|
spirit of <a href="part_one.html#%28part._sec~3ainput-errors%29" data-pltdoc="x">Input Errors</a>. Designing <span class="RktSym">checked-join</span> would
|
||
|
be impossible for you, however. A comparison of the last <a href="part_four.html#%28tech._db._spec%29" class="techoutside" data-pltdoc="x"><span class="techinside">Spec</span></a> in
|
||
|
the schema of <span class="RktSym">db-1</span> with the first one in <span class="RktSym">db-2</span> calls for
|
||
|
a comparison of functions. For practical solutions, see a text on databases. <a href="part_four.html#%28counter._db._%28exercise._ex~3adb-join%29%29" class="ex-end" data-pltdoc="x"></a></p><h3>24<tt> </tt><a name="(part._ch~3asummary4)"></a>Summary</h3><p><div class="SIntrapara">This fourth part of the book is about the design of functions that process
|
||
|
data whose description requires many intertwined definitions. These forms
|
||
|
of data show up everywhere in the real world, from your computer’s local
|
||
|
file system to the world wide web and geometric shapes used in animated
|
||
|
movies. After working through this part of the book carefully, you know
|
||
|
that the <a name="(idx._(gentag._583))"></a>design recipe scales to these forms of data, too:
|
||
|
</div><div class="SIntrapara"><ol><li><p>When the description of program data calls for several mutually
|
||
|
referential data definitions, the design recipe calls for the simultaneous
|
||
|
development of <a name="(idx._(gentag._584))"></a>templates, one per data definition. If a data definition
|
||
|
<span class="stt">A</span> refers to a data definition <span class="stt">B</span>, then the
|
||
|
template <span class="RktSym">function-for-A</span> refers to <span class="RktSym">function-for-B</span> in the
|
||
|
exact same place and manner. Otherwise the design recipes work as before,
|
||
|
function for function.</p></li><li><p>When a function has to process two types of complex data, you need to
|
||
|
distinguish three cases. First, the function may deal with one of the
|
||
|
arguments as if it were atomic. Second, the two arguments are expected to
|
||
|
have the exact same structure, and the function traverses them in a
|
||
|
completely parallel manner. Third, the function may have to deal with all
|
||
|
possible combinations separately. In this case, you make a two-dimensional
|
||
|
table that along one dimension enumerates all kinds of data from one data
|
||
|
definition and along the other one deals with the second kind of
|
||
|
data. Finally you use the table’s cells to formulate conditions and
|
||
|
answers for the various cases.</p><p>This part of the book deals with functions on two complex arguments. If
|
||
|
you ever encounter one of those rare cases where a function receives three
|
||
|
complex pieces of data, you know you need (to imagine) a three-dimensional
|
||
|
table.</p></li></ol></div><div class="SIntrapara">You have now seen all forms of <a name="(idx._(gentag._585))"></a>structural data that you are likely to
|
||
|
encounter over the course of your career, though the details will
|
||
|
differ. If you are ever stuck, remember the <a name="(idx._(gentag._586))"></a>design recipe; it will get you
|
||
|
started.</div></p><div class="navsetbottom"><span class="navleft"><div class="nosearchform"></div> <span class="tocsettoggle"> <a href="javascript:void(0);" title="show/hide table of contents" onclick="TocsetToggle();">contents</a></span></span><span class="navright"> <a href="i3-4.html" title="backward to "Intermezzo 3: Scope and Abstraction"" data-pltdoc="x">← prev</a> <a href="index.html" title="up to "How to Design Programs, Second Edition"" data-pltdoc="x">up</a> <a href="i4-5.html" title="forward to "Intermezzo 4: The Nature of Numbers"" data-pltdoc="x">next →</a></span> </div></div></div><div id="contextindicator"> </div></body></html>
|