976 lines
No EOL
570 KiB
HTML
976 lines
No EOL
570 KiB
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>VI Accumulators</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="racket.css" title="default"/><link rel="stylesheet" type="text/css" href="figure.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="tocviewlink" 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="tocviewselflink" 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>VI </td><td><a href="part_six.html" class="tocviewselflink" data-pltdoc="x">Accumulators</a></td></tr></table><div class="tocviewsublistbottom" style="display: none;" id="tocview_1"><table cellspacing="0" cellpadding="0"><tr><td align="right">31 </td><td><a href="part_six.html#%28part._ch~3aaccumulator-samples%29" class="tocviewlink" data-pltdoc="x">The Loss of Knowledge</a></td></tr><tr><td align="right">32 </td><td><a href="part_six.html#%28part._sec~3adesign-accu%29" class="tocviewlink" data-pltdoc="x">Designing Accumulator-<wbr></wbr>Style Functions</a></td></tr><tr><td align="right">33 </td><td><a href="part_six.html#%28part._ch~3amore-accu%29" class="tocviewlink" data-pltdoc="x">More Uses of Accumulation</a></td></tr><tr><td align="right">34 </td><td><a href="part_six.html#%28part._ch~3asummary6%29" class="tocviewlink" data-pltdoc="x">Summary</a></td></tr></table></div></div></div></div><div class="maincolumn"><div class="main"><div class="versionbox"><span class="version">8.6.0.2</span></div><div class="navsettop"><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="i5-6.html" title="backward to "Intermezzo 5: The Cost of Computation"" 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="part_epilogue.html" title="forward to "Epilogue: Moving On"" data-pltdoc="x">next →</a></span> </div><h3>VI<tt> </tt><a name="(part._part~3asix)"></a>Accumulators</h3><table cellspacing="0" cellpadding="0"><tr><td><p><span class="hspace"> </span><a href="part_six.html#%28part._ch~3aaccumulator-samples%29" class="toclink" data-pltdoc="x">31<span class="hspace"> </span>The Loss of Knowledge</a></p></td></tr><tr><td><p><span class="hspace"> </span><a href="part_six.html#%28part._sec~3aloss~3astructural%29" class="toclink" data-pltdoc="x">31.1<span class="hspace"> </span>A Problem with Structural Processing</a></p></td></tr><tr><td><p><span class="hspace"> </span><a href="part_six.html#%28part._sec~3aloss~3agenerative%29" class="toclink" data-pltdoc="x">31.2<span class="hspace"> </span>A Problem with Generative Recursion</a></p></td></tr><tr><td><p><span class="hspace"> </span><a href="part_six.html#%28part._sec~3adesign-accu%29" class="toclink" data-pltdoc="x">32<span class="hspace"> </span>Designing Accumulator-Style Functions</a></p></td></tr><tr><td><p><span class="hspace"> </span><a href="part_six.html#%28part._sec~3aneed-accu%29" class="toclink" data-pltdoc="x">32.1<span class="hspace"> </span>Recognizing the Need for an Accumulator</a></p></td></tr><tr><td><p><span class="hspace"> </span><a href="part_six.html#%28part._sec~3aaccu-style%29" class="toclink" data-pltdoc="x">32.2<span class="hspace"> </span>Adding Accumulators</a></p></td></tr><tr><td><p><span class="hspace"> </span><a href="part_six.html#%28part._sec~3atrans-accu%29" class="toclink" data-pltdoc="x">32.3<span class="hspace"> </span>Transforming Functions into Accumulator Style</a></p></td></tr><tr><td><p><span class="hspace"> </span><a href="part_six.html#%28part._accu-edit._sec~3aedit3%29" class="toclink" data-pltdoc="x">32.4<span class="hspace"> </span>A Graphical Editor, with Mouse</a></p></td></tr><tr><td><p><span class="hspace"> </span><a href="part_six.html#%28part._ch~3amore-accu%29" class="toclink" data-pltdoc="x">33<span class="hspace"> </span>More Uses of Accumulation</a></p></td></tr><tr><td><p><span class="hspace"> </span><a href="part_six.html#%28part._sec~3amore-accu-trees%29" class="toclink" data-pltdoc="x">33.1<span class="hspace"> </span>Accumulators and Trees</a></p></td></tr><tr><td><p><span class="hspace"> </span><a href="part_six.html#%28part._sec~3amore-accu-mc%29" class="toclink" data-pltdoc="x">33.2<span class="hspace"> </span>Data Representations with Accumulators</a></p></td></tr><tr><td><p><span class="hspace"> </span><a href="part_six.html#%28part._sec~3afractal-acc%29" class="toclink" data-pltdoc="x">33.3<span class="hspace"> </span>Accumulators as Results</a></p></td></tr><tr><td><p><span class="hspace"> </span><a href="part_six.html#%28part._ch~3asummary6%29" class="toclink" data-pltdoc="x">34<span class="hspace"> </span>Summary</a></p></td></tr></table><p>When you ask ISL+ to apply some function <span class="RktSym">f</span> to an argument
|
|
<span class="RktSym">a</span>, you usually get some value <span class="RktSym">v</span>. If you evaluate
|
|
<span class="RktPn">(</span><span class="RktSym">f</span><span class="stt"> </span><span class="RktSym">a</span><span class="RktPn">)</span> again, you get <span class="RktSym">v</span> again. As a matter of fact, you
|
|
get <span class="RktSym">v</span> no matter how often you request the evaluation of
|
|
<span class="RktPn">(</span><span class="RktSym">f</span><span class="stt"> </span><span class="RktSym">a</span><span class="RktPn">)</span>.<span class="refelem"><span class="refcolumn"><span class="refcontent">The function application may also loop
|
|
forever or signal an error, but we ignore these possibilities. We also
|
|
ignore <span class="RktSym">random</span>, which is the true exception to this rule.</span></span></span>
|
|
Whether the function is applied for the first time or the hundredth time,
|
|
whether the application is located in DrRacket’s interactions area or inside
|
|
the function itself, doesn’t matter. The function works according to its
|
|
purpose statement, and that’s all you need to know.</p><p>This principle of context-independence plays a critical role in the design
|
|
of recursive functions. When it comes to design, you are free to assume
|
|
that the function computes what the purpose statement promises—<wbr></wbr>even if
|
|
the function isn’t defined yet. In particular, you are free to use the
|
|
results of recursive calls to create the code of some function, usually in
|
|
one of its <span class="RktSym">cond</span> clauses. The template and coding steps of the
|
|
design recipes for both <a name="(idx._(gentag._705))"></a>structurally and <a name="(idx._(gentag._706))"></a>generative-recursive functions
|
|
rely on this idea.</p><p>While context-independence facilitates the design of functions, it causes
|
|
two problems. In general, context-independence induces a loss of knowledge
|
|
during a recursive evaluation; a function does not “know” whether it is
|
|
called on a complete list or on a piece of that list. For structurally
|
|
recursive programs, this loss of knowledge means that they may have to
|
|
traverse data more than once, inducing a performance cost. For functions
|
|
that employ generative recursion, the loss means that the function may not
|
|
be able to compute the result at all. The preceding part illustrates this
|
|
second problem with a graph traversal function that cannot find a path
|
|
between two nodes for a circular graph.</p><p>This part introduces a variant of the design recipes to address this “loss
|
|
of context” problem. Since we wish to retain the principle that
|
|
<span class="RktPn">(</span><span class="RktSym">f</span><span class="stt"> </span><span class="RktSym">a</span><span class="RktPn">)</span> returns the same result no matter how often or where it is
|
|
evaluated, the only solution is to add <span style="font-weight: bold">an argument that represents
|
|
the context</span> of the function call. We call this additional argument an
|
|
<span style="font-style: italic">accumulator</span>. During the traversal of data, the recursive calls
|
|
continue to receive regular arguments while accumulators change in
|
|
relation to those and the context.</p><p>Designing functions with accumulators correctly is clearly more complex
|
|
than any of the design approaches from the preceding chapters. The key is
|
|
to understand the relationship between the proper arguments and the
|
|
accumulators. The following chapters explain how to design functions with
|
|
accumulators and how they work.</p><h3>31<tt> </tt><a name="(part._ch~3aaccumulator-samples)"></a>The Loss of Knowledge</h3><p>Both functions designed according to structural recipes and the <a name="(idx._(gentag._707))"></a>generative
|
|
one suffer from the loss of knowledge, though in different ways. This
|
|
chapter explains with two examples—<wbr></wbr>one from each category—<wbr></wbr>how the lack
|
|
of contextual knowledge affects the performance of functions. While the
|
|
first section is about structural recursion, the second one addresses
|
|
concerns in the generative realm.</p><h4>31.1<tt> </tt><a name="(part._sec~3aloss~3astructural)"></a>A Problem with Structural Processing</h4><p>Let’s start with a seemingly straightforward example:</p><blockquote><p><span style="font-weight: bold">Sample Problem</span> You are working for a geometer team that will measure the length
|
|
of road segments. The team asked you to design a program that translates these
|
|
relative distances between a series of road points into absolute distances from
|
|
some starting point.</p></blockquote><p><div class="SIntrapara">For example, we might be given a line such as this:
|
|
</div><div class="SIntrapara"><blockquote><p><img style="vertical-align: 0px; margin: -3px -3px -3px -3px;" src="pict_273.png" alt="image" width="406.0" height="58.0"/></p></blockquote></div><div class="SIntrapara">Each number specifies the distance between two dots. What we need is the
|
|
following picture, where each dot is annotated with the distance to the
|
|
left-most end:
|
|
</div><div class="SIntrapara"><blockquote><p><img style="vertical-align: 0px; margin: -3px -3px -3px -3px;" src="pict_274.png" alt="image" width="406.0" height="58.0"/></p></blockquote></div></p><p>Designing a program that performs this calculation is a mere
|
|
exercise in structural function design. <a href="part_six.html#%28counter._%28figure._fig~3arel-abs-dist%29%29" data-pltdoc="x">Figure <span class="FigureRef">177</span></a>
|
|
contains the complete program. When the given list is not <span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span>,
|
|
the natural recursion computes the absolute distance of the remainder of
|
|
the dots to the first one on <span class="RktPn">(</span><span class="RktSym"><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>. Because the first
|
|
is not the actual origin and has a distance of <span class="RktPn">(</span><span class="RktSym"><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> to the
|
|
origin, we must add <span class="RktPn">(</span><span class="RktSym"><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> to each number on the result of
|
|
the natural recursion. This second step—<wbr></wbr>adding a number to each item on a
|
|
list of numbers—<wbr></wbr>requires an auxiliary function.</p><p><div class="SIntrapara"><a name="(idx._(gentag._708))"></a>
|
|
<a name="(idx._(gentag._709))"></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><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">converts a list of relative to absolute distances</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">the first number represents the distance to the origin</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">relative->absolute</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">50</span><span class="hspace"> </span><span class="RktVal">40</span><span class="hspace"> </span><span class="RktVal">70</span><span class="hspace"> </span><span class="RktVal">30</span><span class="hspace"> </span><span class="RktVal">30</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">50</span><span class="hspace"> </span><span class="RktVal">90</span><span class="hspace"> </span><span class="RktVal">160</span><span class="hspace"> </span><span class="RktVal">190</span><span class="hspace"> </span><span class="RktVal">220</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">relative->absolute</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#%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">l</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><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">rest-of-l</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">relative->absolute</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">l</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._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">adjusted</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">add-to-each</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">l</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">rest-of-l</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._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">l</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">adjusted</span><span class="RktPn">)</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_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">adds </span><span class="RktSym">n</span><span class="RktCmt"> to each number on </span><span class="RktSym">l</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"><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">50</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">add-to-each</span><span class="hspace"> </span><span class="RktVal">50</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">40</span><span class="hspace"> </span><span class="RktVal">110</span><span class="hspace"> </span><span class="RktVal">140</span><span class="hspace"> </span><span class="RktVal">170</span><span class="RktVal">)</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">50</span><span class="hspace"> </span><span class="RktVal">90</span><span class="hspace"> </span><span class="RktVal">160</span><span class="hspace"> </span><span class="RktVal">190</span><span class="hspace"> </span><span class="RktVal">220</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">add-to-each</span><span class="hspace"> </span><span class="RktSym">n</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#%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">l</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><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._%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._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="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">add-to-each</span><span class="hspace"> </span><span class="RktSym">n</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">l</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></blockquote><p class="Centertext"><span class="Legend"><span class="FigureTarget"><a name="(counter._(figure._fig~3arel-abs-dist))" x-target-lift="Figure"></a>Figure 177: </span>Converting relative distances to absolute distances</span></p></blockquote></div></p><p><div class="SIntrapara">While designing the program is relatively straightforward, using it on larger
|
|
and larger lists reveals a problem. Consider the evaluation of the
|
|
following expression:
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktPn">(</span><span class="RktSym">relative->absolute</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._build-list%29%29" class="RktValLink" data-pltdoc="x">build-list</a></span><span class="hspace"> </span><span class="RktSym">size</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._add1%29%29" class="RktValLink" data-pltdoc="x">add1</a></span><span class="RktPn">)</span><span class="RktPn">)</span></p></blockquote></div><div class="SIntrapara">As we increase <span class="RktSym">size</span>, the time needed grows even
|
|
faster:</div></p><p><div class="SIntrapara"><blockquote><table cellspacing="0" cellpadding="0"><tr><td align="right"><p><span class="RktSym">size</span></p></td><td align="right"><p><span class="hspace"> </span></p></td><td align="right"><p>1000</p></td><td align="right"><p><span class="hspace"> </span></p></td><td align="right"><p>2000</p></td><td align="right"><p><span class="hspace"> </span></p></td><td align="right"><p>3000</p></td><td align="right"><p><span class="hspace"> </span></p></td><td align="right"><p>4000</p></td><td align="right"><p><span class="hspace"> </span></p></td><td align="right"><p>5000</p></td><td align="right"><p><span class="hspace"> </span></p></td><td align="right"><p>6000</p></td><td align="right"><p><span class="hspace"> </span></p></td><td align="right"><p>7000</p></td></tr><tr><td align="right"><p>time</p></td><td align="right"><p><span class="hspace"> </span></p></td><td align="right"><p>25</p></td><td align="right"><p><span class="hspace"> </span></p></td><td align="right"><p>109</p></td><td align="right"><p><span class="hspace"> </span></p></td><td align="right"><p>234</p></td><td align="right"><p><span class="hspace"> </span></p></td><td align="right"><p>429</p></td><td align="right"><p><span class="hspace"> </span></p></td><td align="right"><p>689</p></td><td align="right"><p><span class="hspace"> </span></p></td><td align="right"><p>978</p></td><td align="right"><p><span class="hspace"> </span></p></td><td align="right"><p>1365</p></td></tr></table></blockquote></div><div class="SIntrapara">Instead of doubling as we go from <span style="font-style: italic"></span>1<span style="font-style: italic"></span>0<span style="font-style: italic"></span>0<span style="font-style: italic"></span>0<span style="font-style: italic"></span> to <span style="font-style: italic"></span>2<span style="font-style: italic"></span>0<span style="font-style: italic"></span>0<span style="font-style: italic"></span>0<span style="font-style: italic"></span> items, the
|
|
time quadruples. This is also the approximate relationship for going from
|
|
<span style="font-style: italic"></span>2<span style="font-style: italic"></span>0<span style="font-style: italic"></span>0<span style="font-style: italic"></span>0<span style="font-style: italic"></span> to <span style="font-style: italic"></span>4<span style="font-style: italic"></span>0<span style="font-style: italic"></span>0<span style="font-style: italic"></span>0<span style="font-style: italic"></span>, and so on.<span class="refelem"><span class="refcolumn"><span class="refcontent">The times will differ
|
|
from computer to computer and year to year. These measurements were
|
|
conducted in 2017 on a MacMini running OS X 10.11; the previous
|
|
measurement took place in 1998, and the times were <span style="font-style: italic"></span>1<span style="font-style: italic"></span>0<span style="font-style: italic"></span>0<span style="font-style: italic">x</span> larger.</span></span></span>
|
|
Using the terminology of <a href="i5-6.html" data-pltdoc="x">Intermezzo 5: The Cost of Computation</a>, we say that the function’s
|
|
performance is <span style="font-style: italic">O</span>(<span style="font-style: italic">n</span><span style="vertical-align: super; font-size: 80%"><span style="font-style: italic"></span>2<span style="font-style: italic"></span></span><span style="font-style: italic"></span>)<span style="font-style: italic"></span> where <span style="font-style: italic">n</span> is the length of the given
|
|
list.</div></p><p><a name="(counter._(exercise._ex~3aadd-to-each-map))"></a><span style="font-weight: bold">Exercise</span> 489. Reformulate <span class="RktSym">add-to-each</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._map%29%29" class="RktValLink" data-pltdoc="x">map</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._lambda%29%29" class="RktStxLink" data-pltdoc="x">lambda</a></span>. <a href="part_six.html#%28counter._%28exercise._ex~3aadd-to-each-map%29%29" class="ex-end" data-pltdoc="x"></a></p><p><div class="SIntrapara"><a name="(counter._(exercise._ex~3arel-abs-.O))"></a><span style="font-weight: bold">Exercise</span> 490. Develop a formula that describes the abstract
|
|
running time of <span class="RktSym">relative->absolute</span>. <span style="font-weight: bold">Hint</span> Evaluate the
|
|
expression
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktPn">(</span><span class="RktSym">relative->absolute</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._build-list%29%29" class="RktValLink" data-pltdoc="x">build-list</a></span><span class="hspace"> </span><span class="RktSym">size</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._add1%29%29" class="RktValLink" data-pltdoc="x">add1</a></span><span class="RktPn">)</span><span class="RktPn">)</span></p></blockquote></div><div class="SIntrapara">by hand. Start by replacing <span class="RktSym">size</span> with 1, 2, and 3. How many
|
|
recursions of <span class="RktSym">relative->absolute</span> and <span class="RktSym">add-to-each</span> are
|
|
required each time? <a href="part_six.html#%28counter._%28exercise._ex~3arel-abs-.O%29%29" class="ex-end" data-pltdoc="x"></a></div></p><p>Considering the simplicity of the problem, the amount of work that the
|
|
program performs is surprising. If we were to convert the same list by
|
|
hand, we would tally up the total distance and just add it to the relative
|
|
distances as we take steps along the line. Why can’t a program do so?</p><p><div class="SIntrapara">Let’s attempt to design a version of the function that is close to
|
|
our manual method. We still start from the list-processing 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">relative->absolute/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#%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">l</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">l</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">relative->absolute/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._rest%29%29" class="RktValLink" data-pltdoc="x">rest</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><span class="RktPn">]</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">Now let’s simulate a hand-evaluation:
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym">relative->absolute/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">3</span><span class="hspace"> </span><span class="RktVal">2</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><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="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="RktVal">3</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="RktPn">(</span><span class="RktSym">relative->absolute/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">2</span><span class="hspace"> </span><span class="RktVal">7</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#%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="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="RktVal">3</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="RktPn">(</span><span class="RktSym"><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="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="RktVal">2</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="RktPn">(</span><span class="RktSym">relative->absolute/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">7</span><span class="RktPn">)</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#%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="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="RktVal">3</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="RktPn">(</span><span class="RktSym"><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="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="RktVal">2</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="RktPn">(</span><span class="RktSym"><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="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="RktVal">7</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="RktPn">(</span><span class="RktSym">relative->absolute/a</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></table></blockquote></div><div class="SIntrapara">The first item of the result list should obviously be <span class="RktVal">3</span>, and it is
|
|
easy to construct this list. But, the second one should be <span class="RktPn">(</span><span class="RktSym"><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="RktVal">2</span><span class="RktPn">)</span>, yet the second instance of <span class="RktSym">relative->absolute/a</span> has no way of
|
|
“knowing” that the first item of the <span style="font-weight: bold">original</span> list is
|
|
<span class="RktVal">3</span>. The “knowledge” is lost.</div></p><p>Again, the problem is that recursive functions are independent of their
|
|
context. A function processes <span class="RktSym">L</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._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="stt"> </span><span class="RktSym">N</span><span class="stt"> </span><span class="RktSym">L</span><span class="RktPn">)</span> the same
|
|
way as 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._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="stt"> </span><span class="RktSym">K</span><span class="stt"> </span><span class="RktSym">L</span><span class="RktPn">)</span>. Indeed, if given <span class="RktSym">L</span> by itself,
|
|
it would also process the list in that way.</p><p>To make up for the loss of “knowledge,” we equip the function with an
|
|
additional parameter: <span class="RktSym">accu-dist</span>. The latter represents the
|
|
accumulated distance, which is the tally that we keep when we convert a
|
|
list of relative distances to a list of absolute distances. Its initial
|
|
value must be <span class="RktVal">0</span>. As the function traverses the list, it must add
|
|
its numbers to the tally.</p><p><div class="SIntrapara">Here is the revised definition: <a name="(idx._(gentag._710))"></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">relative->absolute/a</span><span class="hspace"> </span><span class="RktSym">l</span><span class="hspace"> </span><span class="RktSym">accu-dist</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">l</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">tally</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._%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._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="hspace"> </span><span class="RktSym">accu-dist</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._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="hspace"> </span><span class="RktSym">tally</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">relative->absolute/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._rest%29%29" class="RktValLink" data-pltdoc="x">rest</a></span><span class="hspace"> </span><span class="RktSym">l</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">tally</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">The recursive application consumes the rest of the list and the new
|
|
absolute distance of the current point to the origin. Although both
|
|
arguments are changing for every call, the change in the second one
|
|
strictly depends on the first argument. The function is still a plain
|
|
list-processing procedure.</div></p><p><div class="SIntrapara">Now let’s evaluate our running example again:
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym">relative->absolute/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">3</span><span class="hspace"> </span><span class="RktVal">2</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><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">relative->absolute/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">3</span><span class="hspace"> </span><span class="RktVal">2</span><span class="hspace"> </span><span class="RktVal">7</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">0</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#%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">3</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">relative->absolute/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">2</span><span class="hspace"> </span><span class="RktVal">7</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">3</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#%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">3</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">5</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">relative->absolute/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">7</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">5</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#%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">3</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">5</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">12</span><span class="hspace"> </span><span class="RktSym">???</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#%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">3</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">5</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">12</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></table></blockquote></div><div class="SIntrapara">Stop! Fill in the question marks in line 4.</div></p><p>The hand-evaluation shows just how much the use of an accumulator
|
|
simplifies the conversion process. Each item in the list is processed
|
|
once. When <span class="RktSym">relative->absolute/a</span> reaches the end of the argument
|
|
list, the result is completely determined and no further work is needed. In
|
|
general, the function performs on the order of <span style="font-style: italic">N</span> natural recursion
|
|
steps for a list with <span style="font-style: italic">N</span> items.</p><p>One problem is that, unlike <span class="RktSym">relative->absolute</span>, the new function
|
|
consumes two arguments, not just one. Worse, someone might accidentally
|
|
misuse <span class="RktSym">relative->absolute/a</span> by applying it to a list of numbers
|
|
and a number that isn’t <span class="RktVal">0</span>. We can solve both problems with a
|
|
function definition that uses 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 encapsulate
|
|
<span class="RktSym">relative->absolute/a</span>; <a href="part_six.html#%28counter._%28figure._fig~3arel-abs-human%29%29" data-pltdoc="x">figure <span class="FigureRef">178</span></a> shows the
|
|
result. Now, <span class="RktSym">relative->absolute</span> is indistinguishable from
|
|
<span class="RktSym">relative->absolute.v2</span> with respect to input-output.</p><p><div class="SIntrapara"><a name="(idx._(gentag._711))"></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><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">converts a list of relative to absolute distances</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">the first number represents the distance to the origin</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">relative->absolute.v2</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">50</span><span class="hspace"> </span><span class="RktVal">40</span><span class="hspace"> </span><span class="RktVal">70</span><span class="hspace"> </span><span class="RktVal">30</span><span class="hspace"> </span><span class="RktVal">30</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">50</span><span class="hspace"> </span><span class="RktVal">90</span><span class="hspace"> </span><span class="RktVal">160</span><span class="hspace"> </span><span class="RktVal">190</span><span class="hspace"> </span><span class="RktVal">220</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">relative->absolute.v2</span><span class="hspace"> </span><span class="RktSym">l0</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></td></tr><tr><td><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_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_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="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">relative->absolute/a</span><span class="hspace"> </span><span class="RktSym">l</span><span class="hspace"> </span><span class="RktSym">accu-dist</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">l</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">accu</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._%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._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="hspace"> </span><span class="RktSym">accu-dist</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._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span><span class="hspace"> </span><span class="RktSym">accu</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">relative->absolute/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._rest%29%29" class="RktValLink" data-pltdoc="x">rest</a></span><span class="hspace"> </span><span class="RktSym">l</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">accu</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><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">relative->absolute/a</span><span class="hspace"> </span><span class="RktSym">l0</span><span class="hspace"> </span><span class="RktVal">0</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></blockquote><p class="Centertext"><span class="Legend"><span class="FigureTarget"><a name="(counter._(figure._fig~3arel-abs-human))" x-target-lift="Figure"></a>Figure 178: </span>Converting relative distances with an accumulator</span></p></blockquote></div></p><p><div class="SIntrapara">Now let’s look at how this version of the program performs. To this
|
|
end, we evaluate
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktPn">(</span><span class="RktSym">relative->absolute.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._build-list%29%29" class="RktValLink" data-pltdoc="x">build-list</a></span><span class="hspace"> </span><span class="RktSym">size</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._add1%29%29" class="RktValLink" data-pltdoc="x">add1</a></span><span class="RktPn">)</span><span class="RktPn">)</span></p></blockquote></div><div class="SIntrapara">and tabulate the results for several values of <span class="RktSym">size</span>:</div></p><p><div class="SIntrapara"><blockquote><table cellspacing="0" cellpadding="0"><tr><td align="right"><p><span class="RktSym">size</span></p></td><td align="right"><p><span class="hspace"> </span></p></td><td align="right"><p>1000</p></td><td align="right"><p><span class="hspace"> </span></p></td><td align="right"><p>2000</p></td><td align="right"><p><span class="hspace"> </span></p></td><td align="right"><p>3000</p></td><td align="right"><p><span class="hspace"> </span></p></td><td align="right"><p>4000</p></td><td align="right"><p><span class="hspace"> </span></p></td><td align="right"><p>5000</p></td><td align="right"><p><span class="hspace"> </span></p></td><td align="right"><p>6000</p></td><td align="right"><p><span class="hspace"> </span></p></td><td align="right"><p>7000</p></td></tr><tr><td align="right"><p>time</p></td><td align="right"><p><span class="hspace"> </span></p></td><td align="right"><p>0</p></td><td align="right"><p><span class="hspace"> </span></p></td><td align="right"><p>0</p></td><td align="right"><p><span class="hspace"> </span></p></td><td align="right"><p>0</p></td><td align="right"><p><span class="hspace"> </span></p></td><td align="right"><p>0</p></td><td align="right"><p><span class="hspace"> </span></p></td><td align="right"><p>0</p></td><td align="right"><p><span class="hspace"> </span></p></td><td align="right"><p>1</p></td><td align="right"><p><span class="hspace"> </span></p></td><td align="right"><p>1</p></td></tr></table></blockquote></div><div class="SIntrapara">Amazingly, <span class="RktSym">relative->absolute.v2</span> never takes more than one second to
|
|
process such lists, even for a list of <span style="font-style: italic"></span>7<span style="font-style: italic"></span>0<span style="font-style: italic"></span>0<span style="font-style: italic"></span>0<span style="font-style: italic"></span> numbers. Comparing this
|
|
performance to the one of <span class="RktSym">relative->absolute</span>, you may think that
|
|
accumulators are a miracle cure for all slow-running programs. Unfortunately,
|
|
this isn’t the case, but when a structurally recursive function has to
|
|
re-process the result of the natural recursion you should definitely consider
|
|
the use of accumulators. In this particular case, the performance improved from
|
|
<span style="font-style: italic">O</span>(<span style="font-style: italic">n</span><span style="vertical-align: super; font-size: 80%"><span style="font-style: italic"></span>2<span style="font-style: italic"></span></span><span style="font-style: italic"></span>)<span style="font-style: italic"></span> to <span style="font-style: italic">O</span>(<span style="font-style: italic">n</span>)<span style="font-style: italic"></span>—<wbr></wbr>with an additional large reduction in the
|
|
constant.</div></p><p><div class="SIntrapara"><a name="(counter._(exercise._ex~3arel-abs-from-reverse))"></a><span style="font-weight: bold">Exercise</span> 491. With a bit of design and a bit of
|
|
tinkering, a friend of yours came up with the following solution for the
|
|
sample problem:<span class="refelem"><span class="refcolumn"><span class="refcontent">Adrian German and Mardin Yadegar
|
|
suggested this exercise.</span></span></span> <a name="(idx._(gentag._712))"></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">relative->absolute</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._reverse%29%29" class="RktValLink" data-pltdoc="x">reverse</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._foldr%29%29" class="RktValLink" data-pltdoc="x">foldr</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">f</span><span class="hspace"> </span><span class="RktSym">l</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%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._%2B%29%29" class="RktValLink" data-pltdoc="x">+</a></span><span class="hspace"> </span><span class="RktSym">f</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">l</span><span class="RktPn">)</span><span class="RktPn">)</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._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._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><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._reverse%29%29" class="RktValLink" data-pltdoc="x">reverse</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._rest%29%29" class="RktValLink" data-pltdoc="x">rest</a></span><span class="hspace"> </span><span class="RktSym">l</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">This simple solution merely uses well-known ISL+ functions:
|
|
<span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._reverse%29%29" class="RktValLink" data-pltdoc="x">reverse</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._foldr%29%29" class="RktValLink" data-pltdoc="x">foldr</a></span>. 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._lambda%29%29" class="RktStxLink" data-pltdoc="x">lambda</a></span>, as you know,
|
|
is just a convenience. You may also recall from <a href="part_three.html" data-pltdoc="x">Abstraction</a> 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> is designable with the design recipes presented in the
|
|
first two parts of the book.</div></p><p>Does your friend’s solution mean there is no need for our complicated
|
|
design in this motivational section? For an answer, see
|
|
<a href="part_six.html#%28part._sec~3aneed-accu%29" data-pltdoc="x">Recognizing the Need for an Accumulator</a>, but reflect on the question first. <span style="font-weight: bold">Hint</span> Try to
|
|
design <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._reverse%29%29" class="RktValLink" data-pltdoc="x">reverse</a></span> on your own. <a href="part_six.html#%28counter._%28exercise._ex~3arel-abs-from-reverse%29%29" class="ex-end" data-pltdoc="x"></a></p><h4>31.2<tt> </tt><a name="(part._sec~3aloss~3agenerative)"></a>A Problem with Generative Recursion</h4><p><div class="SIntrapara">Let’s revisit the problem of “traveling” along a path in a graph:
|
|
</div><div class="SIntrapara"><blockquote><p><span style="font-weight: bold">Sample Problem</span> Design an algorithm that checks whether two nodes are
|
|
connected in a <span style="font-style: italic">simple graph</span>. In such a graph, each node has
|
|
exactly one, directional connection to another, and possibly itself.</p></blockquote></div><div class="SIntrapara"><a href="part_five.html#%28part._ch~3abacktrack%29" data-pltdoc="x">Algorithms that Backtrack</a> covers the variant where the algorithm has to
|
|
discover the path. This sample problem is simpler than that because this
|
|
section focuses on the design of an accumulator version of the algorithm.</div></p><p>Consider the sample graph in <a href="part_six.html#%28counter._%28figure._fig~3asim-graph%29%29" data-pltdoc="x">figure <span class="FigureRef">179</span></a>. There are six
|
|
nodes, <span style="font-style: italic">A</span> through <span style="font-style: italic">F</span>, and six connections. A path from <span style="font-style: italic">A</span>
|
|
to <span style="font-style: italic">E</span> must contain <span style="font-style: italic">B</span> and <span style="font-style: italic">C</span>. There is no path, though,
|
|
from <span style="font-style: italic">A</span> to <span style="font-style: italic">F</span> or from any other node besides itself.</p><blockquote class="Figure"><blockquote class="Centerfigure"><blockquote class="FigureInside"><table cellspacing="0" cellpadding="0"><tr><td><p><img style="vertical-align: 0px; margin: -3px -3px -3px -3px;" src="pict_275.png" alt="image" width="355.8" height="72.0"/></p></td><td><p><span class="hspace"> </span></p></td><td><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">a-sg</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">'</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></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">B</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">C</span><span class="hspace"> </span><span class="RktVal">E</span><span class="RktVal">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">D</span><span class="hspace"> </span><span class="RktVal">E</span><span class="RktVal">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">E</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">F</span><span class="hspace"> </span><span class="RktVal">F</span><span class="RktVal">)</span><span class="RktVal">)</span><span class="RktPn">)</span></td></tr></table></blockquote></td></tr></table></blockquote></blockquote><p class="Centertext"><span class="Legend"><span class="FigureTarget"><a name="(counter._(figure._fig~3asim-graph))" x-target-lift="Figure"></a>Figure 179: </span>A simple graph</span></p></blockquote><p><div class="SIntrapara">The right part of <a href="part_six.html#%28counter._%28figure._fig~3asim-graph%29%29" data-pltdoc="x">figure <span class="FigureRef">179</span></a> shows how to represent this
|
|
graph with nested lists. Each node is represented by a list of two symbols. The
|
|
first symbol is the label of the node; the second one is the single node
|
|
that is reachable from the first one. Here are the relevant data definitions:
|
|
</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._simplegraph)"></a><span style="font-style: italic">SimpleGraph</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_six.html#%28tech._connection%29" class="techoutside" data-pltdoc="x"><span class="techinside">Connection</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._connection)"></a><span style="font-style: italic">Connection</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._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="stt"> </span><a href="part_six.html#%28tech._node%29" class="techoutside" data-pltdoc="x"><span class="techinside">Node</span></a><span class="stt"> </span><a href="part_six.html#%28tech._node%29" class="techoutside" data-pltdoc="x"><span class="techinside">Node</span></a><span class="RktPn">)</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">A </span><a name="(tech._node)"></a><span style="font-style: italic">Node</span><span class="RktCmt"> is a </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><div class="SIntrapara">They are straightforward translations of our informal descriptions.</div></p><p><div class="SIntrapara">We already know that the problem calls for generative recursion, and it is
|
|
easy to create the header material: <a name="(idx._(gentag._713))"></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_six.html#%28tech._node%29" class="techoutside" data-pltdoc="x"><span class="techinside">Node</span></a><span class="RktCmt"> </span><a href="part_six.html#%28tech._node%29" class="techoutside" data-pltdoc="x"><span class="techinside">Node</span></a><span class="RktCmt"> </span><a href="part_six.html#%28tech._simplegraph%29" class="techoutside" data-pltdoc="x"><span class="techinside">SimpleGraph</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 there a path from </span><span class="RktSym">origin</span><span class="RktCmt"> to </span><span class="RktSym">destination</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">in the simple graph </span><span class="RktSym">sg</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">path-exists?</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">E</span><span class="hspace"> </span><span class="RktSym">a-sg</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">path-exists?</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">F</span><span class="hspace"> </span><span class="RktSym">a-sg</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></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">path-exists?</span><span class="hspace"> </span><span class="RktSym">origin</span><span class="hspace"> </span><span class="RktSym">destination</span><span class="hspace"> </span><span class="RktSym">sg</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">What we need are answers to the four basic questions of the recipe for
|
|
<a name="(idx._(gentag._714))"></a>generative recursion:
|
|
</div><div class="SIntrapara"><ul><li><p>The problem is trivial if <span class="RktSym">origin</span> is the same as
|
|
<span class="RktSym">destination</span>.</p></li><li><p>The trivial solution is <span class="RktVal">#true</span>.</p></li><li><p>If <span class="RktSym">origin</span> is not the same as <span class="RktSym">destination</span>,
|
|
there is only one thing we can do: step to the immediate neighbor and
|
|
search for <span class="RktSym">destination</span> from there.</p></li><li><p>There is no need to do anything if we find the solution to the new problem.
|
|
If <span class="RktSym">origin</span>’s neighbor is connected to <span class="RktSym">destination</span>,
|
|
then so is <span class="RktSym">origin</span>. Otherwise there is no connection.</p></li></ul></div><div class="SIntrapara">From here we just need to express these answers in ISL+ to obtain a
|
|
full-fledged program.</div></p><p><div class="SIntrapara"><a name="(idx._(gentag._715))"></a>
|
|
<a name="(idx._(gentag._716))"></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_six.html#%28tech._node%29" class="techoutside" data-pltdoc="x"><span class="techinside">Node</span></a><span class="RktCmt"> </span><a href="part_six.html#%28tech._node%29" class="techoutside" data-pltdoc="x"><span class="techinside">Node</span></a><span class="RktCmt"> </span><a href="part_six.html#%28tech._simplegraph%29" class="techoutside" data-pltdoc="x"><span class="techinside">SimpleGraph</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 there a path from </span><span class="RktSym">origin</span><span class="RktCmt"> to </span><span class="RktSym">destination</span><span class="RktCmt"> in </span><span class="RktSym">sg</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">path-exists?</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">E</span><span class="hspace"> </span><span class="RktSym">a-sg</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">path-exists?</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">F</span><span class="hspace"> </span><span class="RktSym">a-sg</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></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">path-exists?</span><span class="hspace"> </span><span class="RktSym">origin</span><span class="hspace"> </span><span class="RktSym">destination</span><span class="hspace"> </span><span class="RktSym">sg</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._symbol~3d~3f%29%29" class="RktValLink" data-pltdoc="x">symbol=?</a></span><span class="hspace"> </span><span class="RktSym">origin</span><span class="hspace"> </span><span class="RktSym">destination</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">#t</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">path-exists?</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">neighbor</span><span class="hspace"> </span><span class="RktSym">origin</span><span class="hspace"> </span><span class="RktSym">sg</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktSym">destination</span></td></tr><tr><td><span class="hspace"> </span><span class="RktSym">sg</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_six.html#%28tech._node%29" class="techoutside" data-pltdoc="x"><span class="techinside">Node</span></a><span class="RktCmt"> </span><a href="part_six.html#%28tech._simplegraph%29" class="techoutside" data-pltdoc="x"><span class="techinside">SimpleGraph</span></a><span class="RktCmt"> -> </span><a href="part_six.html#%28tech._node%29" class="techoutside" data-pltdoc="x"><span class="techinside">Node</span></a></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">determine the node that is connected to </span><span class="RktSym">a-node</span><span class="RktCmt"> in </span><span class="RktSym">sg</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">neighbor</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">A</span><span class="hspace"> </span><span class="RktSym">a-sg</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">B</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">neighbor</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">G</span><span class="hspace"> </span><span class="RktSym">a-sg</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">"neighbor: not a node"</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">neighbor</span><span class="hspace"> </span><span class="RktSym">a-node</span><span class="hspace"> </span><span class="RktSym">sg</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">sg</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">"neighbor: not a node"</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"><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="RktPn">(</span><span class="RktSym"><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="RktPn">(</span><span class="RktSym"><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">sg</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">a-node</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._second%29%29" class="RktValLink" data-pltdoc="x">second</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">sg</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">neighbor</span><span class="hspace"> </span><span class="RktSym">a-node</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">sg</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></blockquote><p class="Centertext"><span class="Legend"><span class="FigureTarget"><a name="(counter._(figure._fig~3apath-exists1))" x-target-lift="Figure"></a>Figure 180: </span>Finding a path in a simple graph</span></p></blockquote></div></p><p><a href="part_six.html#%28counter._%28figure._fig~3apath-exists1%29%29" data-pltdoc="x">Figure <span class="FigureRef">180</span></a> contains the complete program, including the
|
|
function for finding the neighbor of a node in a simple graph—<wbr></wbr>a
|
|
straightforward exercise in structural recursion—<wbr></wbr>and test cases for
|
|
both possible outcomes. Don’t run the program, however. If you do, be ready with your mouse
|
|
to stop the run-away program. Indeed, even a casual look at the function
|
|
suggests that we have a problem. Although the function is supposed to
|
|
produce <span class="RktVal">#false</span> if there is no path from <span class="RktSym">origin</span> to
|
|
<span class="RktSym">destination</span>, the program doesn’t contain <span class="RktVal">#false</span>
|
|
anywhere. Conversely, we need to ask what the function actually does when
|
|
there is no path between two nodes.</p><p><div class="SIntrapara">Take another look at <a href="part_six.html#%28counter._%28figure._fig~3asim-graph%29%29" data-pltdoc="x">figure <span class="FigureRef">179</span></a>. In this simple graph there
|
|
is no path from <span style="font-style: italic">C</span> to <span style="font-style: italic">D</span>. The connection that leaves <span style="font-style: italic">C</span>
|
|
passes right by <span style="font-style: italic">D</span> and instead goes to <span style="font-style: italic">E</span>. So let’s look at a
|
|
hand-evaluation:
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym">path-exists?</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">C</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">D</span><span class="hspace"> </span><span class="RktVal">'</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><img src="pict_276.png" alt="image" width="13" height="2"/><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">F</span><span class="hspace"> </span><span class="RktVal">F</span><span class="RktVal">)</span><span class="RktVal">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktSym">==</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">path-exists?</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">E</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">D</span><span class="hspace"> </span><span class="RktVal">'</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><img src="pict_277.png" alt="image" width="13" height="2"/><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">F</span><span class="hspace"> </span><span class="RktVal">F</span><span class="RktVal">)</span><span class="RktVal">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktSym">==</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">path-exists?</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">B</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">D</span><span class="hspace"> </span><span class="RktVal">'</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><img src="pict_278.png" alt="image" width="13" height="2"/><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">F</span><span class="hspace"> </span><span class="RktVal">F</span><span class="RktVal">)</span><span class="RktVal">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktSym">==</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">path-exists?</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">C</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">D</span><span class="hspace"> </span><span class="RktVal">'</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><img src="pict_279.png" alt="image" width="13" height="2"/><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">F</span><span class="hspace"> </span><span class="RktVal">F</span><span class="RktVal">)</span><span class="RktVal">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">It confirms that as the function recurs, it calls itself with the exact same
|
|
arguments again and again. In other words, the evaluation never stops.</div></p><p>Our problem with <span class="RktSym">path-exists?</span> is again a loss of “knowledge,”
|
|
similar to that of <span class="RktSym">relative->absolute</span> above. Like
|
|
<span class="RktSym">relative->absolute</span>, the design of <span class="RktSym">path-exists?</span> uses a
|
|
recipe and assumes that recursive calls are independent of their
|
|
context. In the case of <span class="RktSym">path-exists?</span> this means, in particular,
|
|
that the function doesn’t “know” whether a previous application in the
|
|
current chain of recursions received the exact same arguments.</p><p>The solution to this design problem follows the pattern of the preceding
|
|
section. We add a parameter, which we call <span class="RktSym">seen</span> and which
|
|
represents the accumulated list of starter nodes that the function has
|
|
encountered, starting with the original application. Its initial value must
|
|
be <span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span>. As the function checks on a specific
|
|
<span class="RktSym">origin</span> and moves to its neighbors, <span class="RktSym">origin</span> is
|
|
added to <span class="RktSym">seen</span>.</p><p><div class="SIntrapara">Here is a first revision of <span class="RktSym">path-exists?</span>, dubbed
|
|
<span class="RktSym">path-exists?/a</span>: <a name="(idx._(gentag._717))"></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_six.html#%28tech._node%29" class="techoutside" data-pltdoc="x"><span class="techinside">Node</span></a><span class="RktCmt"> </span><a href="part_six.html#%28tech._node%29" class="techoutside" data-pltdoc="x"><span class="techinside">Node</span></a><span class="RktCmt"> </span><a href="part_six.html#%28tech._simplegraph%29" class="techoutside" data-pltdoc="x"><span class="techinside">SimpleGraph</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_six.html#%28tech._node%29" class="techoutside" data-pltdoc="x"><span class="techinside">Node</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 there a path from </span><span class="RktSym">origin</span><span class="RktCmt"> to </span><span class="RktSym">destination</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span style="font-weight: bold">assume</span><span class="RktCmt"> there are no paths for the nodes in </span><span class="RktSym">seen</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">path-exists?/a</span><span class="hspace"> </span><span class="RktSym">origin</span><span class="hspace"> </span><span class="RktSym">destination</span><span class="hspace"> </span><span class="RktSym">sg</span><span class="hspace"> </span><span class="RktSym">seen</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._symbol~3d~3f%29%29" class="RktValLink" data-pltdoc="x">symbol=?</a></span><span class="hspace"> </span><span class="RktSym">origin</span><span class="hspace"> </span><span class="RktSym">destination</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><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">path-exists?/a</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">neighbor</span><span class="hspace"> </span><span class="RktSym">origin</span><span class="hspace"> </span><span class="RktSym">sg</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktSym">destination</span></td></tr><tr><td><span class="hspace"> </span><span class="RktSym">sg</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="RktSym">origin</span><span class="hspace"> </span><span class="RktSym">seen</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">The addition of the new parameter alone does not solve our problem, but, as
|
|
the hand-evaluation of
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktPn">(</span><span class="RktSym">path-exists?/a</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">C</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">D</span><span class="hspace"> </span><span class="RktVal">'</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><img src="pict_280.png" alt="image" width="13" height="2"/><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">F</span><span class="hspace"> </span><span class="RktVal">F</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></p></blockquote></div><div class="SIntrapara">shows, it provides the foundation for one:
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktSym">==</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">path-exists?/a</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">E</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">D</span><span class="hspace"> </span><span class="RktVal">'</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><img src="pict_281.png" alt="image" width="13" height="2"/><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">F</span><span class="hspace"> </span><span class="RktVal">F</span><span class="RktVal">)</span><span class="RktVal">)</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">C</span><span class="RktVal">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktSym">==</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">path-exists?/a</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">B</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">D</span><span class="hspace"> </span><span class="RktVal">'</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><img src="pict_282.png" alt="image" width="13" height="2"/><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">F</span><span class="hspace"> </span><span class="RktVal">F</span><span class="RktVal">)</span><span class="RktVal">)</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">E</span><span class="hspace"> </span><span class="RktVal">C</span><span class="RktVal">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktSym">==</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">path-exists?/a</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">C</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">D</span><span class="hspace"> </span><span class="RktVal">'</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><img src="pict_283.png" alt="image" width="13" height="2"/><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">F</span><span class="hspace"> </span><span class="RktVal">F</span><span class="RktVal">)</span><span class="RktVal">)</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">B</span><span class="hspace"> </span><span class="RktVal">E</span><span class="hspace"> </span><span class="RktVal">C</span><span class="RktVal">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">In contrast to the original function, the revised function no longer calls
|
|
itself with the exact same arguments. While the three arguments proper are
|
|
again the same for the third recursive application, the accumulator
|
|
argument is different from that of the first application. Instead of
|
|
<span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span>, it is now <span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">B</span><span class="stt"> </span><span class="RktVal">E</span><span class="stt"> </span><span class="RktVal">C</span><span class="RktVal">)</span>. The new value tells us that
|
|
during the search of a path from <span class="RktVal">'</span><span class="RktVal">C</span> to <span class="RktVal">'</span><span class="RktVal">D</span>, the function
|
|
has inspected <span class="RktVal">'</span><span class="RktVal">B</span>, <span class="RktVal">'</span><span class="RktVal">E</span>, and <span class="RktVal">'</span><span class="RktVal">C</span> as starting
|
|
points.</div></p><p>All we need to do now is to make the algorithm exploit the accumulated
|
|
knowledge. Specifically, the algorithm can determine whether the given
|
|
<span class="RktSym">origin</span> is already an item in <span class="RktSym">seen</span>. If so, the
|
|
problem is also trivially solvable, yielding <span class="RktVal">#false</span> as the
|
|
solution. <a href="part_six.html#%28counter._%28figure._fig~3apath-exists2%29%29" data-pltdoc="x">Figure <span class="FigureRef">181</span></a> contains the definition of
|
|
<span class="RktSym">path-exists.v2?</span>, which is the revision of <span class="RktSym">path-exists?</span>. The
|
|
definition refers 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._member~3f%29%29" class="RktValLink" data-pltdoc="x">member?</a></span>, an ISL+ function.</p><p><div class="SIntrapara"><a name="(idx._(gentag._718))"></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_six.html#%28tech._node%29" class="techoutside" data-pltdoc="x"><span class="techinside">Node</span></a><span class="RktCmt"> </span><a href="part_six.html#%28tech._node%29" class="techoutside" data-pltdoc="x"><span class="techinside">Node</span></a><span class="RktCmt"> </span><a href="part_six.html#%28tech._simplegraph%29" class="techoutside" data-pltdoc="x"><span class="techinside">SimpleGraph</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 there a path from </span><span class="RktSym">origin</span><span class="RktCmt"> to </span><span class="RktSym">destination</span><span class="RktCmt"> in </span><span class="RktSym">sg</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">path-exists.v2?</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">E</span><span class="hspace"> </span><span class="RktSym">a-sg</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">path-exists.v2?</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">F</span><span class="hspace"> </span><span class="RktSym">a-sg</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></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">path-exists.v2?</span><span class="hspace"> </span><span class="RktSym">origin</span><span class="hspace"> </span><span class="RktSym">destination</span><span class="hspace"> </span><span class="RktSym">sg</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_six.html#%28tech._node%29" class="techoutside" data-pltdoc="x"><span class="techinside">Node</span></a><span class="RktCmt"> </span><a href="part_six.html#%28tech._node%29" class="techoutside" data-pltdoc="x"><span class="techinside">Node</span></a><span class="RktCmt"> </span><a href="part_six.html#%28tech._simplegraph%29" class="techoutside" data-pltdoc="x"><span class="techinside">SimpleGraph</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_six.html#%28tech._node%29" class="techoutside" data-pltdoc="x"><span class="techinside">Node</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">path-exists?/a</span><span class="hspace"> </span><span class="RktSym">origin</span><span class="hspace"> </span><span class="RktSym">seen</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._symbol~3d~3f%29%29" class="RktValLink" data-pltdoc="x">symbol=?</a></span><span class="hspace"> </span><span class="RktSym">origin</span><span class="hspace"> </span><span class="RktSym">destination</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">#t</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._member~3f%29%29" class="RktValLink" data-pltdoc="x">member?</a></span><span class="hspace"> </span><span class="RktSym">origin</span><span class="hspace"> </span><span class="RktSym">seen</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">#f</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">path-exists?/a</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">neighbor</span><span class="hspace"> </span><span class="RktSym">origin</span><span class="hspace"> </span><span class="RktSym">sg</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="RktSym">origin</span><span class="hspace"> </span><span class="RktSym">seen</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><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">path-exists?/a</span><span class="hspace"> </span><span class="RktSym">origin</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></table></blockquote></blockquote><p class="Centertext"><span class="Legend"><span class="FigureTarget"><a name="(counter._(figure._fig~3apath-exists2))" x-target-lift="Figure"></a>Figure 181: </span>Finding a path in a simple graph with an accumulator</span></p></blockquote></div></p><p>The definition of <span class="RktSym">path-exists.v2?</span> also eliminates the two minor
|
|
problems with the first revision. By localizing the definition of the
|
|
accumulating function, we can ensure that the first call always uses
|
|
<span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span> as the initial value for <span class="RktSym">seen</span>. And,
|
|
<span class="RktSym">path-exists.v2?</span> satisfies the exact same signature and purpose
|
|
statement as the <span class="RktSym">path-exists?</span> function.</p><p>Still, there is a significant difference between <span class="RktSym">path-exists.v2?</span>
|
|
and <span class="RktSym">relative-to-absolute2</span>. Whereas the latter was equivalent to
|
|
the original function, <span class="RktSym">path-exists.v2?</span> improves on
|
|
<span class="RktSym">path-exists?</span>. While the latter fails to find an answer for some
|
|
inputs, <span class="RktSym">path-exists.v2?</span> finds a solution for any simple graph.</p><p><a name="(counter._(exercise._ex~3afind-path-comp))"></a><span style="font-weight: bold">Exercise</span> 492. Modify the definitions in
|
|
<a href="part_five.html#%28counter._fsm._%28figure._fig~3afind-path-code%29%29" data-pltdoc="x">figure <span class="FigureRef">169</span></a> so that the program produces
|
|
<span class="RktVal">#false</span>, even if it encounters the same origin twice. <a href="part_six.html#%28counter._%28exercise._ex~3afind-path-comp%29%29" class="ex-end" data-pltdoc="x"></a></p><h3>32<tt> </tt><a name="(part._sec~3adesign-accu)"></a>Designing Accumulator-Style Functions</h3><p>The preceding chapter illustrates the need for accumulating extra knowledge
|
|
with two examples. In one case, accumulation makes it easy to understand
|
|
the function and yields one that is far faster than the original
|
|
version. In the other case, accumulation is necessary for the function to
|
|
work properly. In both cases, though, the need for accumulation becomes apparent
|
|
only once a properly designed function exists.</p><p><div class="SIntrapara">Generalizing from the preceding chapter suggests that the design of
|
|
accumulator functions has two major aspects:
|
|
</div><div class="SIntrapara"><ol><li><p>the recognition that a function benefits from an accumulator; and</p></li><li><p>an understanding of what the accumulator represents.</p></li></ol></div><div class="SIntrapara">The first two sections address these two questions. Because the second
|
|
one is a difficult topic, the third section illustrates it with a series
|
|
of examples that convert regular functions into accumulating ones.</div></p><p><div class="SIntrapara"><a name="(idx._(gentag._719))"></a>
|
|
<a name="(idx._(gentag._720))"></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><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"> X] -> [</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"> X]</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">constructs the reverse of </span><span class="RktSym">alox</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">invert</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="RktPn">)</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">c</span><span class="hspace"> </span><span class="RktVal">b</span><span class="hspace"> </span><span class="RktVal">a</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">invert</span><span class="hspace"> </span><span class="RktSym">alox</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">alox</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">add-as-last</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">alox</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">invert</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">alox</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><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">X [</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"> X] -> [</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"> X]</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">adds </span><span class="RktSym">an-x</span><span class="RktCmt"> to the end of </span><span class="RktSym">alox</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">add-as-last</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">c</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">c</span><span class="hspace"> </span><span class="RktVal">b</span><span class="hspace"> </span><span class="RktVal">a</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">add-as-last</span><span class="hspace"> </span><span class="RktSym">an-x</span><span class="hspace"> </span><span class="RktSym">alox</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">alox</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="RktSym">an-x</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._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">alox</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">add-as-last</span><span class="hspace"> </span><span class="RktSym">an-x</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">alox</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></blockquote><p class="Centertext"><span class="Legend"><span class="FigureTarget"><a name="(counter._(figure._fig~3adesign-accu-ex))" x-target-lift="Figure"></a>Figure 182: </span>Design with accumulators, a structural example</span></p></blockquote></div></p><h4>32.1<tt> </tt><a name="(part._sec~3aneed-accu)"></a>Recognizing the Need for an Accumulator</h4><p><div class="SIntrapara">Recognizing the need for accumulators is not an easy task. We have seen two
|
|
reasons, and they are the most prevalent ones. In either case, it is
|
|
critical that we first built a complete function based on a
|
|
<span style="font-weight: bold">conventional</span> <a name="(idx._(gentag._721))"></a>design recipe. Then we study the function and proceed
|
|
as follows:
|
|
</div><div class="SIntrapara"><ol><li><p>If a <a name="(idx._(gentag._722))"></a>structurally recursive function traverses the result of its
|
|
natural recursion with an auxiliary, recursive function, consider the use
|
|
of an accumulator parameter.</p><p>Take a look at the definition of <span class="RktSym">invert</span> in
|
|
<a href="part_six.html#%28counter._%28figure._fig~3adesign-accu-ex%29%29" data-pltdoc="x">figure <span class="FigureRef">182</span></a>. The result of the recursive application
|
|
produces the reverse of the rest of the list. It uses <span class="RktSym">add-as-last</span>
|
|
to add the first item to this reversed list and thus creates the reverse of
|
|
the entire list. This second, auxiliary function is also recursive. We
|
|
have thus identified an accumulator candidate.</p><p><div class="SIntrapara">It is now time to study some hand-evaluations, as in <a href="part_six.html#%28part._sec~3aloss~3astructural%29" data-pltdoc="x">A Problem with Structural Processing</a>,
|
|
to see whether an accumulator helps. Consider the following:
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym">invert</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="RktPn">)</span></td></tr><tr><td><span class="RktSym">==</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">add-as-last</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">a</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">invert</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">b</span><span class="hspace"> </span><span class="RktVal">c</span><span class="RktVal">)</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">add-as-last</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">a</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">add-as-last</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">b</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">invert</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">c</span><span class="RktVal">)</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>...</td></tr><tr><td><span class="RktSym">==</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">add-as-last</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">a</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">add-as-last</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">b</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">c</span><span class="RktVal">)</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">add-as-last</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">c</span><span class="hspace"> </span><span class="RktVal">b</span><span class="RktVal">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktSym">==</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">c</span><span class="hspace"> </span><span class="RktVal">b</span><span class="hspace"> </span><span class="RktVal">a</span><span class="RktVal">)</span></td></tr></table></blockquote></div><div class="SIntrapara">Stop! Replace the dots with the two missing steps. Then you can see that
|
|
<span class="RktSym">invert</span> eventually reaches the end of the given list—<wbr></wbr>just like
|
|
<span class="RktSym">add-as-last</span>—<wbr></wbr>and if it knew which items to put there, there would be
|
|
no need for the auxiliary function.</div></p></li><li><p>If we are dealing with a function based on generative recursion, we
|
|
are faced with a much more difficult task. Our goal must be to understand
|
|
whether the algorithm can fail to produce a result for inputs for which we
|
|
expect a result. If so, adding a parameter that accumulates knowledge may
|
|
help. Because these situations are complex, we defer the discussion of
|
|
an example to <a href="part_six.html#%28part._ch~3amore-accu%29" data-pltdoc="x">More Uses of Accumulation</a>.</p></li></ol></div></p><p><a name="(counter._(exercise._ex~3ainvert-.O))"></a><span style="font-weight: bold">Exercise</span> 493. Argue that, in the terminology of <a href="i5-6.html" data-pltdoc="x">Intermezzo 5: The Cost of Computation</a>,
|
|
<span class="RktSym">invert</span> consumes <span style="font-style: italic">O</span>(<span style="font-style: italic">n</span><span style="vertical-align: super; font-size: 80%"><span style="font-style: italic"></span>2<span style="font-style: italic"></span></span><span style="font-style: italic"></span>)<span style="font-style: italic"></span> time when the given list consists
|
|
of <span style="font-style: italic">n</span> items. <a href="part_six.html#%28counter._%28exercise._ex~3ainvert-.O%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._(exercise._ex~3aneed-accu))"></a><span style="font-weight: bold">Exercise</span> 494. Does the insertion <span class="RktSym">sort></span> function from
|
|
<a href="part_two.html#%28part._sec~3asort.I%29" data-pltdoc="x">Auxiliary Functions that Recur</a> need an accumulator? If so, why? If not, why not? <a href="part_six.html#%28counter._%28exercise._ex~3aneed-accu%29%29" class="ex-end" data-pltdoc="x"></a></p><h4>32.2<tt> </tt><a name="(part._sec~3aaccu-style)"></a>Adding Accumulators</h4><p><div class="SIntrapara">Once you have decided that an existing function should be equipped with an
|
|
accumulator, take these two steps:
|
|
</div><div class="SIntrapara"><ul><li><p>Determine the knowledge that the accumulator represents, what kind of data
|
|
to use, and how the knowledge is acquired as data.</p><p>For example, for the conversion of relative distances to absolute
|
|
distances, it suffices to accumulate the total distance encountered so
|
|
far. As the function processes the list of relative distances, it adds each
|
|
new relative distance found to the accumulator’s current value. For the
|
|
routing problem, the accumulator remembers every node encountered. As the
|
|
path-checking function traverses the graph, it <span class="RktSym"><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>es each new
|
|
node on to the accumulator.</p><p><div class="SIntrapara">In general, you will want to proceed as follows.
|
|
</div><div class="SIntrapara"><ol><li><p><div class="SIntrapara">Create an <a name="(idx._(gentag._723))"></a>accumulator 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><span class="RktCmt">Domain -> Range </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">function</span><span class="hspace"> </span><span class="RktSym">d0</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><span class="RktCmt">Domain AccuDomain -> Range</span></td></tr><tr><td><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><span style="font-weight: bold">accumulator</span><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">function/a</span><span class="hspace"> </span><span class="RktSym">d</span><span class="hspace"> </span><span class="RktSym">a</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">function/a</span><span class="hspace"> </span><span class="RktSym">d0</span><span class="hspace"> </span><span class="RktSym">a0</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">Sketch a manual evaluation of an application of <span class="RktSym">function</span> to understand
|
|
the nature of the accumulator.</div></p></li><li><p>Determine the kind of data that the accumulator tracks.</p><p>Write down a <a name="(idx._(gentag._724))"></a>statement that explains the accumulator as a relationship between
|
|
the argument <span class="RktSym">d</span> of the auxiliary <span class="RktSym">function/a</span> and the original
|
|
argument <span class="RktSym">d0</span>.</p><p><span style="font-weight: bold">Note</span> The relationship remains constant, also called
|
|
<span style="font-weight: bold">invariant</span>, over the course of the evaluation. Because of this
|
|
property, an accumulator statement is often called an <span style="font-style: italic">invariant</span>.</p></li><li><p>Use the invariant to determine the initial value <span class="RktSym">a0</span> for
|
|
<span class="RktSym">a</span>.</p></li><li><p>Also exploit the invariant to determine how to compute the
|
|
accumulator for the recursive function calls within the definition of
|
|
<span class="RktSym">function/a</span>.</p></li></ol></div></p></li><li><p>Exploit the accumulator’s knowledge for the design of <span class="RktSym">function/a</span>.</p><p>For a structurally recursive function, the accumulator’s value is typically used
|
|
in the base case, that is, 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> clause that does not recur. For
|
|
functions that use generative-recursive functions, the accumulated knowledge
|
|
might be used in an existing base case, in a new base case, or in 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> clauses that deal with generative recursion.</p></li></ul></div><div class="SIntrapara">As you can see, the key is the precise description of the role of the
|
|
<a name="(idx._(gentag._725))"></a>accumulator. It is therefore important to practice this skill.</div></p><p><div class="SIntrapara">Let’s take a look at the <span class="RktSym">invert</span> example:<a name="(idx._(gentag._726))"></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">invert.v2</span><span class="hspace"> </span><span class="RktSym">alox0</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><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"> X] ??? -> [</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"> X]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">constructs the reverse of </span><span class="RktSym">alox</span></td></tr><tr><td><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><span style="font-weight: bold">accumulator</span><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">invert/a</span><span class="hspace"> </span><span class="RktSym">alox</span><span class="hspace"> </span><span class="RktSym">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._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">alox</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">invert/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._rest%29%29" class="RktValLink" data-pltdoc="x">rest</a></span><span class="hspace"> </span><span class="RktSym">alox</span><span class="RktPn">)</span><span class="hspace"> </span><span class="highlighted"><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="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></span><span class="RktPn">)</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="RktPn">(</span><span class="RktSym">invert/a</span><span class="hspace"> </span><span class="RktSym">alox0</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">As illustrated in the preceding section, this template suffices to sketch a
|
|
manual evaluation of an example such as
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktPn">(</span><span class="RktSym">invert</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="RktPn">)</span></p></blockquote></div><div class="SIntrapara">Here is the idea:
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktSym">==</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">invert/a</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="RktSym">a0</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktSym">==</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">invert/a</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</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="highlighted"><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">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="RktSym">a0</span></span><span class="RktPn">)</span></td></tr><tr><td><span class="RktSym">==</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">invert/a</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">c</span><span class="RktVal">)</span><span class="hspace"> </span><span class="highlighted"><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">b</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">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="RktSym">a0</span></span><span class="RktPn">)</span></td></tr><tr><td><span class="RktSym">==</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">invert/a</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span><span class="hspace"> </span><span class="highlighted"><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">c</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">b</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">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="RktSym">a0</span></span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">This sketch suggests that <span class="RktSym">invert/a</span> can keep track of all the items it
|
|
has seen in a list that tracks the difference between <span class="RktSym">alox0</span> and
|
|
<span class="RktSym">a</span> in reverse order. The initial value is clearly <span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span>; updating
|
|
the accumulator inside of <span class="RktSym">invert/a</span> 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._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span> produces exactly
|
|
the desired value when <span class="RktSym">invert/a</span> reaches <span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span>.</div></p><p><div class="SIntrapara">Here is a refined template that includes these insights: <a name="(idx._(gentag._727))"></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">invert.v2</span><span class="hspace"> </span><span class="RktSym">alox0</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><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"> X] [</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"> X] -> [</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"> X]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">constructs the reverse of </span><span class="RktSym">alox</span></td></tr><tr><td><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><span style="font-weight: bold">accumulator</span><span class="RktCmt"> </span><span class="RktSym">a</span><span class="RktCmt"> is the list of all those </span></td></tr><tr><td><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">items on </span><span class="RktSym">alox0</span><span class="RktCmt"> that precede </span><span class="RktSym">alox</span><span class="RktCmt"> </span></td></tr><tr><td><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">in reverse order</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">invert/a</span><span class="hspace"> </span><span class="RktSym">alox</span><span class="hspace"> </span><span class="RktSym">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._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">alox</span><span class="RktPn">)</span><span class="hspace"> </span><span class="highlighted"><span class="RktSym">a</span></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">invert/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._rest%29%29" class="RktValLink" data-pltdoc="x">rest</a></span><span class="hspace"> </span><span class="RktSym">alox</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="highlighted"><span class="RktPn">(</span><span class="RktSym"><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><span class="RktSym"><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">alox</span><span class="RktPn">)</span><span class="stt"> </span><span class="RktSym">a</span><span class="RktPn">)</span></span><span class="RktPn">)</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="RktPn">(</span><span class="RktSym">invert/a</span><span class="hspace"> </span><span class="RktSym">alox0</span><span class="hspace"> </span><span class="highlighted"><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span></span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">While the body 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._local%29%29" class="RktStxLink" data-pltdoc="x">local</a></span> definition initializes the accumulator
|
|
with <span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span>, the recursive call 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._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span> to add the current
|
|
head of <span class="RktSym">alox</span> to the accumulator. In the base case, <span class="RktSym">invert/a</span>
|
|
uses the knowledge in the accumulator, the reversed list.</div></p><p>Note how, once again, <span class="RktSym">invert.v2</span> merely traverses the list. In
|
|
contrast, <span class="RktSym">invert</span> reprocesses every result of its natural
|
|
recursion with <span class="RktSym">add-as-last</span>. Stop! Measure how much faster
|
|
<span class="RktSym">invert.v2</span> runs than <span class="RktSym">invert</span>.</p><p><span style="font-weight: bold">Terminology</span> Programmers use the phrase <span style="font-style: italic">accumulator-style
|
|
function</span> to discuss functions that use an accumulator
|
|
parameter. Examples of functions in accumulator style are
|
|
<span class="RktSym">relative->absolute/a</span>, <span class="RktSym">invert/a</span>, and <span class="RktSym">path-exists?/a</span>.</p><h4>32.3<tt> </tt><a name="(part._sec~3atrans-accu)"></a>Transforming Functions into Accumulator Style</h4><p>Articulating the accumulator statement is difficult, but, without formulating
|
|
a good invariant, it is impossible to understand an accumulator-style
|
|
function. Since the goal of a programmer is to make sure that others who
|
|
follow understand the code easily, practicing this skill is critical. And
|
|
formulating invariants deserves a lot of practice.</p><p>The goal of this section is to study the formulation of accumulator
|
|
statements with three case studies: a summation function, the factorial
|
|
function, and a tree-traversal function. Each such case is about the
|
|
conversion of a structurally recursive function into accumulator
|
|
style. None actually calls for the use of an accumulator parameter. But they
|
|
are easily understood and, with the elimination of all other distractions,
|
|
using such examples allows us to focus on the articulation of the
|
|
accumulator invariant.</p><p><div class="SIntrapara">For the first example, consider these definitions of the <span class="RktSym">sum</span>
|
|
function: <a name="(idx._(gentag._728))"></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">sum.v1</span><span class="hspace"> </span><span class="RktSym">alon</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">alon</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">0</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#%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._first%29%29" class="RktValLink" data-pltdoc="x">first</a></span><span class="hspace"> </span><span class="RktSym">alon</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">sum.v1</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">alon</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">Here is the first step toward an accumulator version: <a name="(idx._(gentag._729))"></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">sum.v2</span><span class="hspace"> </span><span class="RktSym">alon0</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><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_one.html#%28tech._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a></td></tr><tr><td><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">computes the sum of the numbers on </span><span class="RktSym">alon</span></td></tr><tr><td><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><span style="font-weight: bold">accumulator</span><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">sum/a</span><span class="hspace"> </span><span class="RktSym">alon</span><span class="hspace"> </span><span class="RktSym">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._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">alon</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">sum/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._rest%29%29" class="RktValLink" data-pltdoc="x">rest</a></span><span class="hspace"> </span><span class="RktSym">alon</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="highlighted"><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="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></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="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">sum/a</span><span class="hspace"> </span><span class="RktSym">alon0</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">Stop! Supply a signature and a test case that works for both.</div></p><p>As suggested by our first step, we have put the template for <span class="RktSym">sum/a</span>
|
|
into 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, added an accumulator parameter, and
|
|
renamed the parameter of <span class="RktSym">sum</span> .</p><blockquote class="Figure"><blockquote class="Centerfigure"><blockquote class="FigureInside"><table cellspacing="0" cellpadding="0"><tr><td><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym">sum.v1</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">10</span><span class="hspace"> </span><span class="RktVal">4</span><span class="RktVal">)</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#%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">10</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">sum.v1</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">4</span><span class="RktVal">)</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#%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">10</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._%2B%29%29" class="RktValLink" data-pltdoc="x">+</a></span><span class="hspace"> </span><span class="RktVal">4</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">sum.v1</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="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#%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">10</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._%2B%29%29" class="RktValLink" data-pltdoc="x">+</a></span><span class="hspace"> </span><span class="RktVal">4</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._%2B%29%29" class="RktValLink" data-pltdoc="x">+</a></span><span class="hspace"> </span><span class="RktVal">0</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td>...</td></tr><tr><td><span class="RktSym">==</span><span class="hspace"> </span><span class="RktVal">14</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">sum.v2</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">10</span><span class="hspace"> </span><span class="RktVal">4</span><span class="RktVal">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktSym">==</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">sum/a</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">10</span><span class="hspace"> </span><span class="RktVal">4</span><span class="RktVal">)</span><span class="hspace"> </span><span class="RktSym">a0</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktSym">==</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">sum/a</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">4</span><span class="RktVal">)</span><span class="hspace"> </span>...<span class="hspace"> </span><span class="RktVal">10</span><span class="hspace"> </span>...<span class="hspace"> </span><span class="RktSym">a0</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktSym">==</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">sum/a</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span><span class="hspace"> </span>...<span class="hspace"> </span><span class="RktVal">4</span><span class="hspace"> </span>...<span class="hspace"> </span><span class="RktVal">10</span><span class="hspace"> </span>...<span class="hspace"> </span><span class="RktSym">a0</span><span class="RktPn">)</span></td></tr><tr><td>...</td></tr><tr><td><span class="RktSym">==</span><span class="hspace"> </span><span class="RktVal">14</span></td></tr></table></td></tr></table></blockquote></blockquote><p class="Centertext"><span class="Legend"><span class="FigureTarget"><a name="(counter._(figure._fig~3asum-accu))" x-target-lift="Figure"></a>Figure 183: </span>Calculating with accumulator-style templates</span></p></blockquote><p><div class="SIntrapara"><a href="part_six.html#%28counter._%28figure._fig~3asum-accu%29%29" data-pltdoc="x">Figure <span class="FigureRef">183</span></a> shows two side-by-side sketches of
|
|
hand-evaluations. A comparison immediately suggests the central idea,
|
|
namely,
|
|
that <span class="RktSym">sum/a</span> can use the accumulator to add up the numbers it
|
|
encounters. Concerning the accumulator invariant, the calculations suggest
|
|
<span class="RktSym">a</span> represents the sum of the numbers encountered so far:
|
|
</div><div class="SIntrapara"><blockquote><p><span class="RktSym">a</span> is the sum of the numbers that <span class="RktSym">alon</span> lacks from <span class="RktSym">alon0</span></p></blockquote></div><div class="SIntrapara">For example, the invariant forces the following relationships to hold:
|
|
</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>if </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 class="RktSym">alon0</span></p></td><td align="right" style="border-bottom: 1px solid black;"><p><span class="hspace"> </span></p></td><td align="right" style="border-bottom: 1px solid black;"><p> is </p></td><td align="right" style="border-bottom: 1px solid black;"><p><span class="hspace"> </span></p></td><td align="right" style="border-bottom: 1px solid black;"><p><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">10</span><span class="stt"> </span><span class="RktVal">4</span><span class="stt"> </span><span class="RktVal">6</span><span class="RktVal">)</span></p></td><td align="right" style="border-bottom: 1px solid black;"><p><span class="hspace"> </span></p></td><td align="right" style="border-bottom: 1px solid black;"><p><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">10</span><span class="stt"> </span><span class="RktVal">4</span><span class="stt"> </span><span class="RktVal">6</span><span class="RktVal">)</span></p></td><td align="right" style="border-bottom: 1px solid black;"><p><span class="hspace"> </span></p></td><td align="right" style="border-bottom: 1px solid black;"><p><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">10</span><span class="stt"> </span><span class="RktVal">4</span><span class="stt"> </span><span class="RktVal">6</span><span class="RktVal">)</span></p></td></tr><tr><td align="left"><p>and </p></td><td align="left"><p><span class="hspace"> </span></p></td><td align="right"><p><span class="RktSym">alon</span></p></td><td align="right"><p><span class="hspace"> </span></p></td><td align="right"><p> is </p></td><td align="right"><p><span class="hspace"> </span></p></td><td align="right"><p><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">4</span><span class="stt"> </span><span class="RktVal">6</span><span class="RktVal">)</span></p></td><td align="right"><p><span class="hspace"> </span></p></td><td align="right"><p><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">6</span><span class="RktVal">)</span></p></td><td align="right"><p><span class="hspace"> </span></p></td><td align="right"><p><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span></p></td></tr><tr><td align="left"><p>then </p></td><td align="left"><p><span class="hspace"> </span></p></td><td align="right"><p><span class="RktSym">a</span></p></td><td align="right"><p><span class="hspace"> </span></p></td><td align="right"><p> should be </p></td><td align="right"><p><span class="hspace"> </span></p></td><td align="right"><p><span class="RktVal">10</span></p></td><td align="right"><p><span class="hspace"> </span></p></td><td align="right"><p><span class="RktVal">14</span></p></td><td align="right"><p><span class="hspace"> </span></p></td><td align="right"><p><span class="RktVal">20</span></p></td></tr></table></blockquote></div></p><p><div class="SIntrapara">Given this precise invariant, the rest of the design is straightforward: <a name="(idx._(gentag._730))"></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">sum.v2</span><span class="hspace"> </span><span class="RktSym">alon0</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><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_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="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">computes the sum of the numbers on </span><span class="RktSym">alon</span></td></tr><tr><td><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><span style="font-weight: bold">accumulator</span><span class="RktCmt"> </span><span class="RktSym">a</span><span class="RktCmt"> is the sum of the numbers </span></td></tr><tr><td><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">that </span><span class="RktSym">alon</span><span class="RktCmt"> lacks from </span><span class="RktSym">alon0</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">sum/a</span><span class="hspace"> </span><span class="RktSym">alon</span><span class="hspace"> </span><span class="RktSym">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._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">alon</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">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">sum/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._rest%29%29" class="RktValLink" data-pltdoc="x">rest</a></span><span class="hspace"> </span><span class="RktSym">alon</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._%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._first%29%29" class="RktValLink" data-pltdoc="x">first</a></span><span class="hspace"> </span><span class="RktSym">alon</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">a</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><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">sum/a</span><span class="hspace"> </span><span class="RktSym">alon0</span><span class="hspace"> </span><span class="RktVal">0</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">If <span class="RktSym">alon</span> is <span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span>, <span class="RktSym">sum/a</span> returns
|
|
<span class="RktSym">a</span> because it represents the sum of all numbers on <span class="RktSym">alon</span>.
|
|
The invariant also implies that <span class="RktVal">0</span> is the initial value for
|
|
<span class="RktSym">a0</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._%2B%29%29" class="RktValLink" data-pltdoc="x">+</a></span> updates the accumulator by adding the number
|
|
that is about to be “forgotten”—<wbr></wbr><span class="RktPn">(</span><span class="RktSym"><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">alox</span><span class="RktPn">)</span>—<wbr></wbr>to the
|
|
accumulator <span class="RktSym">a</span>.</div></p><p><a name="(counter._(exercise._ex~3asum-accu-inex))"></a><span style="font-weight: bold">Exercise</span> 495. Complete the manual evaluation of
|
|
<span class="RktPn">(</span><span class="RktSym">sum/a</span><span class="stt"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">10</span><span class="stt"> </span><span class="RktVal">4</span><span class="RktVal">)</span><span class="stt"> </span><span class="RktVal">0</span><span class="RktPn">)</span> in <a href="part_six.html#%28counter._%28figure._fig~3asum-accu%29%29" data-pltdoc="x">figure <span class="FigureRef">183</span></a>. Doing so
|
|
shows that the <span class="RktSym">sum</span> and <span class="RktSym">sum.v2</span> add up the given
|
|
numbers in reverse order. While <span class="RktSym">sum</span> adds up the numbers from
|
|
right to left, the accumulator-style version adds them up from left to
|
|
right.</p><p><span style="font-weight: bold">Note on Numbers</span> Remember that for exact numbers, this difference has
|
|
no effect on the final result. For inexact numbers, the difference can be
|
|
significant. See the exercises at the end of <a href="i5-6.html" data-pltdoc="x">Intermezzo 5: The Cost of Computation</a>. <a href="part_six.html#%28counter._%28exercise._ex~3asum-accu-inex%29%29" class="ex-end" data-pltdoc="x"></a></p><p><div class="SIntrapara">For the second example, we turn to the well-known factorial
|
|
function: <a name="(idx._(gentag._731))"></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_two.html#%28tech._n%29" class="techoutside" data-pltdoc="x"><span class="techinside">N</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">computes </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="RktSym">n</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._-%29%29" class="RktValLink" data-pltdoc="x"><span class="nobreak">-</span></a></span><span class="stt"> </span><span class="RktSym">n</span><span class="stt"> </span><span class="RktVal">1</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._-%29%29" class="RktValLink" data-pltdoc="x"><span class="nobreak">-</span></a></span><span class="stt"> </span><span class="RktSym">n</span><span class="stt"> </span><span class="RktVal">2</span><span class="RktPn">)</span><span class="stt"> </span>...<span class="stt"> </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">!.v1</span><span class="hspace"> </span><span class="RktVal">3</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">6</span><span class="RktPn">)</span><span class="hspace"> </span><span class="refelem"><span class="refcolumn"><span class="refcontent">The factorial function is useful for the analysis of algorithms.</span></span></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">!.v1</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._zero~3f%29%29" class="RktValLink" data-pltdoc="x">zero?</a></span><span class="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">1</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#%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">n</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">!.v1</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._sub1%29%29" class="RktValLink" data-pltdoc="x">sub1</a></span><span class="hspace"> </span><span class="RktSym">n</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">While <span class="RktSym">relative-2-absolute</span> and <span class="RktSym">invert</span> processed lists,
|
|
the factorial function works on natural numbers, which its template reflects.</div></p><p><div class="SIntrapara">We proceed as before with a template for an accumulator-style version: <a name="(idx._(gentag._732))"></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">!.v2</span><span class="hspace"> </span><span class="RktSym">n0</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_two.html#%28tech._n%29" class="techoutside" data-pltdoc="x"><span class="techinside">N</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></td></tr><tr><td><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">computes </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="RktSym">n</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._-%29%29" class="RktValLink" data-pltdoc="x"><span class="nobreak">-</span></a></span><span class="stt"> </span><span class="RktSym">n</span><span class="stt"> </span><span class="RktVal">1</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._-%29%29" class="RktValLink" data-pltdoc="x"><span class="nobreak">-</span></a></span><span class="stt"> </span><span class="RktSym">n</span><span class="stt"> </span><span class="RktVal">2</span><span class="RktPn">)</span><span class="stt"> </span>...<span class="stt"> </span><span class="RktVal">1</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><span style="font-weight: bold">accumulator</span><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">!/a</span><span class="hspace"> </span><span class="RktSym">n</span><span class="hspace"> </span><span class="RktSym">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._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._zero~3f%29%29" class="RktValLink" data-pltdoc="x">zero?</a></span><span class="hspace"> </span><span class="RktSym">n</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</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._sub1%29%29" class="RktValLink" data-pltdoc="x">sub1</a></span><span class="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="highlighted"><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="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></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="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</span><span class="hspace"> </span><span class="RktSym">n0</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">followed by a sketch of a hand-evaluation:
|
|
</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">!.v1</span><span class="hspace"> </span><span class="RktVal">3</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#%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="RktPn">(</span><span class="RktSym">!.v1</span><span class="hspace"> </span><span class="RktVal">2</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#%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="RktPn">(</span><span class="RktSym"><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">2</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">!.v1</span><span class="hspace"> </span><span class="RktVal">1</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td>...</td></tr><tr><td><span class="RktSym">==</span><span class="hspace"> </span><span class="RktVal">6</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">!.v2</span><span class="hspace"> </span><span class="RktVal">3</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</span><span class="hspace"> </span><span class="RktVal">3</span><span class="hspace"> </span><span class="RktSym">a0</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</span><span class="hspace"> </span><span class="RktVal">2</span><span class="hspace"> </span>...<span class="hspace"> </span><span class="RktVal">3</span><span class="hspace"> </span>...<span class="hspace"> </span><span class="RktSym">a0</span><span class="RktPn">)</span></td></tr><tr><td>...</td></tr><tr><td><span class="RktSym">==</span><span class="hspace"> </span><span class="RktVal">6</span></td></tr></table></td></tr></table></blockquote></div><div class="SIntrapara">The left column indicates how the original version works; the right one
|
|
sketches how the accumulator-style function proceeds. Both structurally traverse a
|
|
natural number until they reach <span class="RktVal">0</span>. While the original version
|
|
schedules only multiplications, the accumulator keeps track of each
|
|
number as the structural traversal descends through the given natural
|
|
number.</div></p><p><div class="SIntrapara">Given the goal of multiplying these numbers, <span class="RktSym">!/a</span> can use the
|
|
accumulator to multiply the numbers immediately:
|
|
</div><div class="SIntrapara"><blockquote><p><span class="RktSym">a</span> is the product of the natural numbers in the interval [<span class="RktSym">n0</span>,<span class="RktSym">n</span>).</p></blockquote></div><div class="SIntrapara">In particular, when <span class="RktSym">n0</span> is <span class="RktVal">3</span> and <span class="RktSym">n</span> is <span class="RktVal">1</span>,
|
|
<span class="RktSym">a</span> is <span class="RktVal">6</span>.</div></p><p><a name="(counter._(exercise._ex~3afactorial-inv))"></a><span style="font-weight: bold">Exercise</span> 496. What should the value of <span class="RktSym">a</span> be when
|
|
<span class="RktSym">n0</span> is <span class="RktVal">10</span> and <span class="RktSym">n</span> is <span class="RktVal">8</span>? <a href="part_six.html#%28counter._%28exercise._ex~3afactorial-inv%29%29" class="ex-end" data-pltdoc="x"></a></p><p><div class="SIntrapara">Using this invariant we can easily pick the initial value for
|
|
<span class="RktSym">a</span>—<wbr></wbr>it is <span class="RktVal">1</span>—<wbr></wbr>and we know that multiplying the current
|
|
accumulator with <span class="RktSym">n</span> is the proper update operation: <a name="(idx._(gentag._733))"></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">!.v2</span><span class="hspace"> </span><span class="RktSym">n0</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_two.html#%28tech._n%29" class="techoutside" data-pltdoc="x"><span class="techinside">N</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_two.html#%28tech._n%29" class="techoutside" data-pltdoc="x"><span class="techinside">N</span></a></td></tr><tr><td><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">computes </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="RktSym">n</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._-%29%29" class="RktValLink" data-pltdoc="x"><span class="nobreak">-</span></a></span><span class="stt"> </span><span class="RktSym">n</span><span class="stt"> </span><span class="RktVal">1</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._-%29%29" class="RktValLink" data-pltdoc="x"><span class="nobreak">-</span></a></span><span class="stt"> </span><span class="RktSym">n</span><span class="stt"> </span><span class="RktVal">2</span><span class="RktPn">)</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">1</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><span style="font-weight: bold">accumulator</span><span class="RktCmt"> </span><span class="RktSym">a</span><span class="RktCmt"> is the product of the </span></td></tr><tr><td><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">natural numbers in the interval [</span><span class="RktSym">n0</span><span class="RktCmt">,</span><span class="RktSym">n</span><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">!/a</span><span class="hspace"> </span><span class="RktSym">n</span><span class="hspace"> </span><span class="RktSym">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._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._zero~3f%29%29" class="RktValLink" data-pltdoc="x">zero?</a></span><span class="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">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</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._sub1%29%29" class="RktValLink" data-pltdoc="x">sub1</a></span><span class="hspace"> </span><span class="RktSym">n</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="RktSym">n</span><span class="hspace"> </span><span class="RktSym">a</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><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">!/a</span><span class="hspace"> </span><span class="RktSym">n0</span><span class="hspace"> </span><span class="RktVal">1</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">It also follows from the accumulator statement that when <span class="RktSym">n</span> is
|
|
<span class="RktVal">0</span>, the accumulator is the product of <span class="RktSym">n</span> through
|
|
<span class="RktVal">1</span>, meaning it is the desired result. So, like <span class="RktSym">sum</span>,
|
|
<span class="RktSym">!/a</span> returns <span class="RktSym">a</span> in this case and uses the result of the
|
|
recursion in the second case.</div></p><p><a name="(counter._(exercise._ex~3atime-factorial))"></a><span style="font-weight: bold">Exercise</span> 497. Like <span class="RktSym">sum</span>, <span class="RktSym">!.v1</span><span class="RktMeta"></span> performs the
|
|
primitive computations, multiplication in this case, in reverse
|
|
order. Surprisingly, this affects the performance of the function in a
|
|
negative manner.</p><p>Measure how long it takes to evaluate <span class="RktPn">(</span><span class="RktSym">!.v1</span><span class="stt"> </span><span class="RktVal">20</span><span class="RktPn">)</span> <span style="font-style: italic"></span>1<span style="font-style: italic">,</span>0<span style="font-style: italic"></span>0<span style="font-style: italic"></span>0<span style="font-style: italic"></span>
|
|
times. Recall that <span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._time%29%29" class="RktStxLink" data-pltdoc="x">time</a></span><span class="stt"> </span><span class="RktSym">an-expression</span><span class="RktPn">)</span> function determines how
|
|
long it takes to run <span class="RktSym">an-expression</span>. <a href="part_six.html#%28counter._%28exercise._ex~3atime-factorial%29%29" class="ex-end" data-pltdoc="x"></a></p><p>For the third and last example, we use a function that measures the height
|
|
of simplified binary trees. The example illustrates that accumulator-style
|
|
programming applies to all kinds of data, not just those defined with
|
|
single self-references. Indeed, it is as commonly used for complicated data
|
|
definitions as it is for lists and natural numbers.</p><p><div class="SIntrapara">Here are the relevant 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">node</span><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym">left</span><span class="hspace"> </span><span class="RktSym">right</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._tree)"></a><span style="font-style: italic">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="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">make-node</span><span class="stt"> </span><a href="part_six.html#%28tech._tree%29" class="techoutside" data-pltdoc="x"><span class="techinside">Tree</span></a><span class="stt"> </span><a href="part_six.html#%28tech._tree%29" class="techoutside" data-pltdoc="x"><span class="techinside">Tree</span></a><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">example</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">make-node</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">make-node</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">make-node</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><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">These trees carry no information; their leaves are <span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span>. Still,
|
|
there are many different trees, as <a href="part_six.html#%28counter._%28figure._fig~3asim-bt-ex%29%29" data-pltdoc="x">figure <span class="FigureRef">184</span></a> shows; it
|
|
also uses suggestive graphics to bring across what these pieces of data
|
|
look like as trees.</div></p><p><div class="SIntrapara">One property that one may wish to compute is the height of such a tree: <a name="(idx._(gentag._734))"></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">height</span><span class="hspace"> </span><span class="RktSym">abt</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">abt</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">0</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#%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._max%29%29" class="RktValLink" data-pltdoc="x">max</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">height</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">node-left</span><span class="hspace"> </span><span class="RktSym">abt</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">height</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">node-right</span><span class="hspace"> </span><span class="RktSym">abt</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">1</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! Supply a signature and a test.
|
|
The table in <a href="part_six.html#%28counter._%28figure._fig~3asim-bt-ex%29%29" data-pltdoc="x">figure <span class="FigureRef">184</span></a> indicates how to measure the
|
|
height of a tree, though it leaves the notion somewhat ambiguous: it is
|
|
either the number of nodes from the root of the tree to the highest leaf
|
|
or the number of connections on such a path. The <span class="RktSym">height</span> function
|
|
follows the second option.</div></p><blockquote class="Figure"><blockquote class="Centerfigure"><blockquote class="FigureInside"><table cellspacing="0" cellpadding="0"><tr><td valign="bottom"><p><img style="vertical-align: 0px; margin: -3px -3px -3px -3px;" src="pict_284.png" alt="image" width="206.0" height="31.0"/></p></td><td valign="bottom"><p><span class="hspace"> </span></p></td><td valign="bottom"><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span></td></tr><tr><td valign="bottom"><p><img style="vertical-align: 0px; margin: -3px -3px -3px -3px;" src="pict_285.png" alt="image" width="206.0" height="106.0"/></p></td><td valign="bottom"><p><span class="hspace"> </span></p></td><td valign="bottom"><span class="RktPn">(</span><span class="RktSym">make-node</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></td></tr><tr><td valign="bottom"><p><span class="hspace"> </span></p></td><td valign="bottom"><p><span class="hspace"> </span></p></td><td valign="bottom"><p><span class="hspace"> </span></p></td></tr><tr><td valign="bottom"><p><img style="vertical-align: -0.0px; margin: -3px -3px -3px -3px;" src="pict_286.png" alt="image" width="206.0" height="231.0"/></p></td><td valign="bottom"><p><span class="hspace"> </span></p></td><td valign="bottom"><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="RktPn">(</span><span class="RktSym">make-node</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">make-node</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><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></td></tr></table></blockquote></blockquote><p class="Centertext"><span class="Legend"><span class="FigureTarget"><a name="(counter._(figure._fig~3asim-bt-ex))" x-target-lift="Figure"></a>Figure 184: </span>Some stripped-down binary trees</span></p></blockquote><p><div class="SIntrapara">To transform this function into an accumulator-style function, we follow the
|
|
standard path. We begin with an appropriate template: <a name="(idx._(gentag._735))"></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">height.v2</span><span class="hspace"> </span><span class="RktSym">abt0</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_six.html#%28tech._tree%29" class="techoutside" data-pltdoc="x"><span class="techinside">Tree</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></td></tr><tr><td><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">measures the height of </span><span class="RktSym">abt</span></td></tr><tr><td><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><span style="font-weight: bold">accumulator</span><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">height/a</span><span class="hspace"> </span><span class="RktSym">abt</span><span class="hspace"> </span><span class="RktSym">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._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">abt</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">height/a</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">node-left</span><span class="hspace"> </span><span class="RktSym">abt</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="highlighted"><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="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></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">height/a</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">node-right</span><span class="hspace"> </span><span class="RktSym">abt</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="highlighted"><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="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></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="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">height/a</span><span class="hspace"> </span><span class="RktSym">abt0</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">As always, the problem is to determine what knowledge the accumulator
|
|
represents. One obvious choice is the number of traversed branches:
|
|
</div><div class="SIntrapara"><blockquote><p><span class="RktSym">a</span> is the number of steps it takes to reach
|
|
<span class="RktSym">abt</span> from <span class="RktSym">abt0</span>.</p></blockquote></div></p><p><div class="SIntrapara">Illustrating this accumulator invariant is best done with a graphical example.
|
|
Take a second look at <a href="part_six.html#%28counter._%28figure._fig~3asim-bt-ex%29%29" data-pltdoc="x">figure <span class="FigureRef">184</span></a>. The bottom-most tree comes
|
|
with two annotations, each pointing out one subtree:
|
|
</div><div class="SIntrapara"><ol><li><p>If <span class="RktSym">abt0</span> is the complete tree and <span class="RktSym">abt</span> is the subtree
|
|
pointed to by the circled <span style="font-style: italic"></span>1<span style="font-style: italic"></span>, the accumulator’s value must be <span class="RktVal">1</span> because it
|
|
takes exactly one step to get from the root of <span class="RktSym">abt</span> to the root of
|
|
<span class="RktSym">abt0</span>.</p></li><li><p>In the same spirit, for the subtree labeled <span style="font-style: italic"></span>2<span style="font-style: italic"></span> the accumulator is
|
|
<span class="RktVal">2</span> because it takes two steps to get to this place.</p></li></ol></div></p><p><div class="SIntrapara">As for the preceding two examples, the invariant basically dictates how to follow
|
|
the rest of the <a name="(idx._(gentag._736))"></a>design recipe for accumulators: the initial value for <span class="RktSym">a</span>
|
|
is <span class="RktVal">0</span>; the update operation is <span class="RktSym"><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>; and the base case uses the
|
|
accumulated knowledge by returning it. Translating this into code yields the
|
|
following skeleton definition: <a name="(idx._(gentag._737))"></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">height.v2</span><span class="hspace"> </span><span class="RktSym">abt0</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_six.html#%28tech._tree%29" class="techoutside" data-pltdoc="x"><span class="techinside">Tree</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_two.html#%28tech._n%29" class="techoutside" data-pltdoc="x"><span class="techinside">N</span></a></td></tr><tr><td><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">measures the height of </span><span class="RktSym">abt</span></td></tr><tr><td><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><span style="font-weight: bold">accumulator</span><span class="RktCmt"> </span><span class="RktSym">a</span><span class="RktCmt"> is the number of steps </span></td></tr><tr><td><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">it takes to reach </span><span class="RktSym">abt</span><span class="RktCmt"> from </span><span class="RktSym">abt0</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">height/a</span><span class="hspace"> </span><span class="RktSym">abt</span><span class="hspace"> </span><span class="RktSym">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._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">abt</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">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">height/a</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">node-left</span><span class="hspace"> </span><span class="RktSym">abt</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._%2B%29%29" class="RktValLink" data-pltdoc="x">+</a></span><span class="hspace"> </span><span class="RktSym">a</span><span class="hspace"> </span><span class="RktVal">1</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">height/a</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">node-right</span><span class="hspace"> </span><span class="RktSym">abt</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._%2B%29%29" class="RktValLink" data-pltdoc="x">+</a></span><span class="hspace"> </span><span class="RktSym">a</span><span class="hspace"> </span><span class="RktVal">1</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><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="RktPn">(</span><span class="RktSym">height/a</span><span class="hspace"> </span><span class="RktSym">abt0</span><span class="hspace"> </span><span class="RktVal">0</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">But, in contrast to the first two examples, <span class="RktSym">a</span> is not the final
|
|
result. 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, the two recursive calls yield two
|
|
values. The design recipe for structural functions dictates that we combine those
|
|
in order to formulate an answer for this case; the dots above indicate that we
|
|
still need to pick an operation that combines these values.</div></p><p><div class="SIntrapara"><a name="(idx._(gentag._738))"></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_six.html#%28tech._tree%29" class="techoutside" data-pltdoc="x"><span class="techinside">Tree</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></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">measures the height of </span><span class="RktSym">abt0</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">height.v2</span><span class="hspace"> </span><span class="RktSym">example</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">3</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">height.v2</span><span class="hspace"> </span><span class="RktSym">abt0</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_six.html#%28tech._tree%29" class="techoutside" data-pltdoc="x"><span class="techinside">Tree</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_two.html#%28tech._n%29" class="techoutside" data-pltdoc="x"><span class="techinside">N</span></a></td></tr><tr><td><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">measures the height of </span><span class="RktSym">abt</span></td></tr><tr><td><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><span style="font-weight: bold">accumulator</span><span class="RktCmt"> </span><span class="RktSym">a</span><span class="RktCmt"> is the number of steps </span></td></tr><tr><td><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">it takes to reach </span><span class="RktSym">abt</span><span class="RktCmt"> from </span><span class="RktSym">abt0</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">height/a</span><span class="hspace"> </span><span class="RktSym">abt</span><span class="hspace"> </span><span class="RktSym">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._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">abt</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">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#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._max%29%29" class="RktValLink" data-pltdoc="x">max</a></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">height/a</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">node-left</span><span class="hspace"> </span><span class="RktSym">abt</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._%2B%29%29" class="RktValLink" data-pltdoc="x">+</a></span><span class="hspace"> </span><span class="RktSym">a</span><span class="hspace"> </span><span class="RktVal">1</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">height/a</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">node-right</span><span class="hspace"> </span><span class="RktSym">abt</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._%2B%29%29" class="RktValLink" data-pltdoc="x">+</a></span><span class="hspace"> </span><span class="RktSym">a</span><span class="hspace"> </span><span class="RktVal">1</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><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">height/a</span><span class="hspace"> </span><span class="RktSym">abt0</span><span class="hspace"> </span><span class="RktVal">0</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></blockquote><p class="Centertext"><span class="Legend"><span class="FigureTarget"><a name="(counter._(figure._fig~3aheight-accu))" x-target-lift="Figure"></a>Figure 185: </span>The accumulator-style version of <span style="font-style: italic">height</span></span></p></blockquote></div></p><p>Following the design recipe also tells us that we need to interpret the two
|
|
values to find the appropriate function. According to the purpose statement for
|
|
<span class="RktSym">height/a</span>, the first value is the height of the left subtree, and the
|
|
second one is the height of the right one. Given that we are interested in the
|
|
height of <span class="RktSym">abt</span> itself and that the height is the largest number of steps
|
|
it takes to reach a leaf, we use 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._max%29%29" class="RktValLink" data-pltdoc="x">max</a></span> function to pick the proper
|
|
one; see <a href="part_six.html#%28counter._%28figure._fig~3aheight-accu%29%29" data-pltdoc="x">figure <span class="FigureRef">185</span></a> for the complete definition.</p><p><div class="SIntrapara"><span style="font-weight: bold">Note on an Alternative Design</span> In addition to counting the number of
|
|
steps it takes to reach a node, an accumulator function could hold on to
|
|
the largest height encountered so far. Here is the accumulator statement
|
|
for the design idea:
|
|
</div><div class="SIntrapara"><blockquote><p>The first accumulator represents the
|
|
number of steps it takes to reach <span class="RktSym">abt</span> from (the root of)
|
|
<span class="RktSym">abt0</span>. The second one stands for the height of the part in
|
|
<span class="RktSym">abt0</span> that is strictly to the left of <span class="RktSym">abt</span>.</p></blockquote></div><div class="SIntrapara">Clearly, this statement assumes a template with two accumulator
|
|
parameters, something we have not encountered before:
|
|
<a name="(idx._(gentag._739))"></a>
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><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="RktCmt">;</span><span class="RktCmt"> </span><a href="part_six.html#%28tech._tree%29" class="techoutside" data-pltdoc="x"><span class="techinside">Tree</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_two.html#%28tech._n%29" class="techoutside" data-pltdoc="x"><span class="techinside">N</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></td></tr><tr><td><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">measures the height of </span><span class="RktSym">abt</span></td></tr><tr><td><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><span style="font-weight: bold">accumulator</span><span class="RktCmt"> </span><span class="RktSym">s</span><span class="RktCmt"> is the number of steps </span></td></tr><tr><td><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">it takes to reach </span><span class="RktSym">abt</span><span class="RktCmt"> from </span><span class="RktSym">abt0</span></td></tr><tr><td><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><span style="font-weight: bold">accumulator</span><span class="RktCmt"> </span><span class="RktSym">m</span><span class="RktCmt"> is the maximal height of</span></td></tr><tr><td><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">the part of </span><span class="RktSym">abt0</span><span class="RktCmt"> that is to the left of </span><span class="RktSym">abt</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">h/a</span><span class="hspace"> </span><span class="RktSym">abt</span><span class="hspace"> </span><span class="RktSym">s</span><span class="hspace"> </span><span class="RktSym">m</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">abt</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">h/a</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">node-left</span><span class="hspace"> </span><span class="RktSym">abt</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="highlighted"><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="RktSym">s</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><span class="hspace"> </span><span class="highlighted"><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="RktSym">m</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><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">h/a</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">node-right</span><span class="hspace"> </span><span class="RktSym">abt</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="highlighted"><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="RktSym">s</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><span class="hspace"> </span><span class="highlighted"><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="RktSym">m</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><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="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></table></blockquote></div></p><p><a name="(counter._(exercise._ex~3aheight-accu))"></a><span style="font-weight: bold">Exercise</span> 498. Complete <span class="RktSym">height.v3</span>.
|
|
<span style="font-weight: bold">Hint</span> The bottom-most tree of <a href="part_six.html#%28counter._%28figure._fig~3asim-bt-ex%29%29" data-pltdoc="x">figure <span class="FigureRef">184</span></a>
|
|
contains no subtree to the left of the subtree marked with <span style="font-style: italic"></span>1<span style="font-style: italic"></span>.
|
|
It contains one complete path from root to tree in the part of the tree
|
|
that is to the left of the subtree marked with <span style="font-style: italic"></span>2<span style="font-style: italic"></span>; this path consists
|
|
of two steps. <a href="part_six.html#%28counter._%28exercise._ex~3aheight-accu%29%29" class="ex-end" data-pltdoc="x"></a></p><p>This second design has a more complex accumulator invariant than the first
|
|
one. By implication, its implementation requires more care than the first
|
|
one. At the same time, it comes without any obvious advantages.</p><p>Our point is that different accumulator invariants yield different
|
|
variants. You can design both variants systematically, following the same
|
|
design recipe. When you have complete function definitions, you can compare
|
|
and contrast the results, and you can then decide which one to keep, based
|
|
on evidence. <span style="font-weight: bold">End</span></p><p><a name="(counter._(exercise._ex~3api-accu))"></a><span style="font-weight: bold">Exercise</span> 499. Design an accumulator-style version of
|
|
<span class="RktSym">product</span>, the function that computes the product of a list of
|
|
numbers. Stop when you have formulated the accumulator invariant and have
|
|
someone check it.</p><p>The performance of <span class="RktSym">product</span> is <span style="font-style: italic">O</span>(<span style="font-style: italic">n</span>)<span style="font-style: italic"></span> where <span style="font-style: italic">n</span> is the
|
|
length of the list. Does the accumulator version improve on this? <a href="part_six.html#%28counter._%28exercise._ex~3api-accu%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._(exercise._ex~3alength-accu))"></a><span style="font-weight: bold">Exercise</span> 500. Design an accumulator-style version of
|
|
<span class="RktSym">how-many</span>, which is the function that determines the number of
|
|
items on a list. Stop when you have formulated the invariant
|
|
and have someone check it.</p><p>The performance of <span class="RktSym">how-many</span> is <span style="font-style: italic">O</span>(<span style="font-style: italic">n</span>)<span style="font-style: italic"></span> where <span style="font-style: italic">n</span> is the
|
|
length of the list. Does the accumulator version improve on this?</p><p>When you evaluate <span class="RktPn">(</span><span class="RktSym">how-many</span><span class="stt"> </span><span class="RktSym">some-non-empty-list</span><span class="RktPn">)</span> by hand, <span style="font-style: italic">n</span>
|
|
applications 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._add1%29%29" class="RktValLink" data-pltdoc="x">add1</a></span> are pending by the time the function reaches
|
|
<span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span>—<wbr></wbr>where <span style="font-style: italic">n</span> is the number of items on the list. Computer
|
|
scientists sometime say that <span class="RktSym">how-many</span> needs <span style="font-style: italic">O</span>(<span style="font-style: italic">n</span>)<span style="font-style: italic"></span> space to
|
|
<span class="refelem"><span class="refcolumn"><span class="refcontent">Computer scientists refer to this space as <span style="font-style: italic">stack
|
|
space</span>, but you can safely ignore this terminology for now.</span></span></span>
|
|
represent these pending function applications. Does the accumulator reduce
|
|
the amount of space needed to compute the result? <a href="part_six.html#%28counter._%28exercise._ex~3alength-accu%29%29" class="ex-end" data-pltdoc="x"></a></p><p><div class="SIntrapara"><a name="(counter._(exercise._ex~3aadd-pi-accu))"></a><span style="font-weight: bold">Exercise</span> 501. Design an accumulator-style version of
|
|
<span class="RktSym">add-to-pi</span>. The function adds a natural number 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._pi%29%29" class="RktValLink" data-pltdoc="x">pi</a></span> without 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._%2B%29%29" class="RktValLink" data-pltdoc="x">+</a></span>: <a name="(idx._(gentag._740))"></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_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._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">adds </span><span class="RktSym">n</span><span class="RktCmt"> to </span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._pi%29%29" class="RktValLink" data-pltdoc="x">pi</a></span><span class="RktCmt"> without using </span><span class="RktSym"><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></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-within%29%29" class="RktStxLink" data-pltdoc="x">check-within</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">add-to-pi</span><span class="hspace"> </span><span class="RktVal">2</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._%2B%29%29" class="RktValLink" data-pltdoc="x">+</a></span><span class="hspace"> </span><span class="RktVal">2</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._pi%29%29" class="RktValLink" data-pltdoc="x">pi</a></span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">0.001</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">add-to-pi</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._zero~3f%29%29" class="RktValLink" data-pltdoc="x">zero?</a></span><span class="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</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._pi%29%29" class="RktValLink" data-pltdoc="x">pi</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#%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="hspace"> </span><span class="RktPn">(</span><span class="RktSym">add-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._sub1%29%29" class="RktValLink" data-pltdoc="x">sub1</a></span><span class="hspace"> </span><span class="RktSym">n</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">Stop when you have formulated the accumulator invariant and have someone check it. <a href="part_six.html#%28counter._%28exercise._ex~3aadd-pi-accu%29%29" class="ex-end" data-pltdoc="x"></a></div></p><p><a name="(counter._(exercise._ex~3apalindrome))"></a><span style="font-weight: bold">Exercise</span> 502. Design the function <span class="RktSym">palindrome</span>, which
|
|
accepts a non-empty list and constructs a palindrome by mirroring the list around
|
|
the last item. When given <span class="RktPn">(</span><span class="RktSym"><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="stt"> </span><span class="RktVal">"abc"</span><span class="RktPn">)</span>, it yields <span class="RktPn">(</span><span class="RktSym"><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="stt"> </span><span class="RktVal">"abcba"</span><span class="RktPn">)</span>.</p><p><div class="SIntrapara"><span style="font-weight: bold">Hint</span> Here is a solution designed by function composition: <a name="(idx._(gentag._741))"></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"> </span><a href="part_one.html#%28tech._1string%29" class="techoutside" data-pltdoc="x"><span class="techinside">1String</span></a><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"> </span><a href="part_one.html#%28tech._1string%29" class="techoutside" data-pltdoc="x"><span class="techinside">1String</span></a><span class="RktCmt">]</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">creates a palindrome from </span><span class="RktSym">s0</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">mirror</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="RktVal">"abc"</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._explode%29%29" class="RktValLink" data-pltdoc="x">explode</a></span><span class="hspace"> </span><span class="RktVal">"abcba"</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="RktPn">(</span><span class="RktSym">mirror</span><span class="hspace"> </span><span class="RktSym">s0</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._append%29%29" class="RktValLink" data-pltdoc="x">append</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">all-but-last</span><span class="hspace"> </span><span class="RktSym">s0</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="RktPn">(</span><span class="RktSym">last</span><span class="hspace"> </span><span class="RktSym">s0</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._reverse%29%29" class="RktValLink" data-pltdoc="x">reverse</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">all-but-last</span><span class="hspace"> </span><span class="RktSym">s0</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">See <a href="part_two.html#%28part._sec~3agen-funcs%29" data-pltdoc="x">Auxiliary Functions that Generalize</a> for <span class="RktSym">last</span>; design <span class="RktSym">all-but-last</span> in an
|
|
analogous manner.</div></p><p><div class="SIntrapara">This solution traverses <span class="RktSym">s0</span> four times:
|
|
</div><div class="SIntrapara"><ol><li><p>via <span class="RktSym">all-but-last</span>,</p></li><li><p>via <span class="RktSym">last</span>,</p></li><li><p>via <span class="RktSym">all-but-last</span> again, and</p></li><li><p>via <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._reverse%29%29" class="RktValLink" data-pltdoc="x">reverse</a></span>, which is ISL+’s version of <span class="RktSym">invert</span>.</p></li></ol></div><div class="SIntrapara">Even 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._local%29%29" class="RktStxLink" data-pltdoc="x">local</a></span> definition for the result of <span class="RktSym">all-but-last</span>, the
|
|
function needs three traversals. While these traversals aren’t “stacked” and
|
|
therefore don’t have a disastrous impact on the function’s performance, an
|
|
accumulator version can compute the same result with a single traversal. <a href="part_six.html#%28counter._%28exercise._ex~3apalindrome%29%29" class="ex-end" data-pltdoc="x"></a></div></p><p><div class="SIntrapara"><a name="(counter._(exercise._ex~3agauss-fast))"></a><span style="font-weight: bold">Exercise</span> 503. <a href="part_five.html#%28counter._%28exercise._ex~3atriangulate2%29%29" data-pltdoc="x">Exercise 467</a> implicitly asks for the
|
|
design of a function that rotates a <a href="part_two.html#%28tech._matrix%29" class="techoutside" data-pltdoc="x"><span class="techinside">Matrix</span></a> until the first
|
|
coefficient of the first row differs from <span class="RktVal">0</span>. In the context of
|
|
<a href="part_five.html#%28counter._%28exercise._ex~3atriangulate2%29%29" data-pltdoc="x">Exercise 467</a>, the solution calls for a generative-recursive
|
|
function that creates a new matrix by shifting the first row to the end
|
|
when it encounters a <span class="RktVal">0</span> in the first position. Here is the solution:
|
|
<a name="(idx._(gentag._742))"></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_two.html#%28tech._matrix%29" class="techoutside" data-pltdoc="x"><span class="techinside">Matrix</span></a><span class="RktCmt"> -> </span><a href="part_two.html#%28tech._matrix%29" class="techoutside" data-pltdoc="x"><span class="techinside">Matrix</span></a><span class="RktCmt"> </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">finds a row that doesn</span><span class="RktCmt">'</span><span class="RktCmt">t start with 0 and</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">uses it as the first one</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span style="font-weight: bold">generative</span><span class="RktCmt"> moves the first row to last place </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span style="font-weight: bold">no termination</span><span class="RktCmt"> if all rows start with </span><span class="RktVal">0</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"><a href="https://docs.racket-lang.org/teachpack/2htdpimage.html#%28def._%28%28lib._2htdp%2Fimage..rkt%29._rotate%29%29" class="RktValLink" data-pltdoc="x">rotate</a></span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">(</span><span class="RktVal">0</span><span class="hspace"> </span><span class="RktVal">4</span><span class="hspace"> </span><span class="RktVal">5</span><span class="RktVal">)</span><span class="hspace"> </span><span class="RktVal">(</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="RktVal">)</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">(</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="RktVal">)</span><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">0</span><span class="hspace"> </span><span class="RktVal">4</span><span class="hspace"> </span><span class="RktVal">5</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="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/teachpack/2htdpimage.html#%28def._%28%28lib._2htdp%2Fimage..rkt%29._rotate%29%29" class="RktValLink" data-pltdoc="x">rotate</a></span><span class="hspace"> </span><span class="RktSym">M</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._not%29%29" class="RktValLink" data-pltdoc="x">not</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"><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="RktPn">(</span><span class="RktSym"><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">M</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">0</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">M</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/teachpack/2htdpimage.html#%28def._%28%28lib._2htdp%2Fimage..rkt%29._rotate%29%29" class="RktValLink" data-pltdoc="x">rotate</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._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._rest%29%29" class="RktValLink" data-pltdoc="x">rest</a></span><span class="hspace"> </span><span class="RktSym">M</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="RktPn">(</span><span class="RktSym"><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">M</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><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">Stop! Modify this function so that it signals an error when all rows start
|
|
with <span class="RktVal">0</span>.</div></p><p><div class="SIntrapara">If you measure this function on large instances of <a href="part_two.html#%28tech._matrix%29" class="techoutside" data-pltdoc="x"><span class="techinside">Matrix</span></a>, you get a
|
|
surprising result:
|
|
</div><div class="SIntrapara"><blockquote><table cellspacing="0" cellpadding="0"><tr><td align="right"><p>rows in <span class="RktSym">M</span></p></td><td align="right"><p><span class="hspace"> </span></p></td><td align="center"><p>1000</p></td><td align="center"><p><span class="hspace"> </span></p></td><td align="right"><p>2000</p></td><td align="right"><p><span class="hspace"> </span></p></td><td align="right"><p>3000</p></td><td align="right"><p><span class="hspace"> </span></p></td><td align="right"><p>4000</p></td><td align="right"><p><span class="hspace"> </span></p></td><td align="right"><p>5000</p></td></tr><tr><td align="right"><p><span class="RktSym"><a href="https://docs.racket-lang.org/teachpack/2htdpimage.html#%28def._%28%28lib._2htdp%2Fimage..rkt%29._rotate%29%29" class="RktValLink" data-pltdoc="x">rotate</a></span></p></td><td align="right"><p><span class="hspace"> </span></p></td><td align="center"><p>17</p></td><td align="center"><p><span class="hspace"> </span></p></td><td align="right"><p>66</p></td><td align="right"><p><span class="hspace"> </span></p></td><td align="right"><p>151</p></td><td align="right"><p><span class="hspace"> </span></p></td><td align="right"><p>272</p></td><td align="right"><p><span class="hspace"> </span></p></td><td align="right"><p>436</p></td></tr></table></blockquote></div><div class="SIntrapara">As the number of rows increases from <span style="font-style: italic"></span>1<span style="font-style: italic">,</span>0<span style="font-style: italic"></span>0<span style="font-style: italic"></span>0<span style="font-style: italic"></span> to <span style="font-style: italic"></span>5<span style="font-style: italic">,</span>0<span style="font-style: italic"></span>0<span style="font-style: italic"></span>0<span style="font-style: italic"></span>, the time
|
|
spent by <span class="RktSym"><a href="https://docs.racket-lang.org/teachpack/2htdpimage.html#%28def._%28%28lib._2htdp%2Fimage..rkt%29._rotate%29%29" class="RktValLink" data-pltdoc="x">rotate</a></span> does not increase by a factor of five but by twenty.</div></p><p><div class="SIntrapara">The problem is that <span class="RktSym"><a href="https://docs.racket-lang.org/teachpack/2htdpimage.html#%28def._%28%28lib._2htdp%2Fimage..rkt%29._rotate%29%29" class="RktValLink" data-pltdoc="x">rotate</a></span> 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._append%29%29" class="RktValLink" data-pltdoc="x">append</a></span>, which makes a
|
|
brand-new list like <span class="RktPn">(</span><span class="RktSym"><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">M</span><span class="RktPn">)</span> only to add <span class="RktPn">(</span><span class="RktSym"><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">M</span><span class="RktPn">)</span> at the
|
|
end. If <span class="RktSym">M</span> consists of <span style="font-style: italic"></span>1<span style="font-style: italic">,</span>0<span style="font-style: italic"></span>0<span style="font-style: italic"></span>0<span style="font-style: italic"></span> rows and the last row is the
|
|
only one with a non-<span class="RktVal">0</span> coefficient, that’s roughly
|
|
</div><div class="SIntrapara"><blockquote class="SCentered"><p><img src="pict_287.png" alt="image" width="140" height="10"/></p></blockquote></div><div class="SIntrapara">lists. How many lists do we get if <span class="RktSym">M</span> consists of <span style="font-style: italic"></span>5<span style="font-style: italic">,</span>0<span style="font-style: italic"></span>0<span style="font-style: italic"></span>0<span style="font-style: italic"></span>
|
|
lines?</div></p><p><div class="SIntrapara">Now suppose we conjecture that the accumulator-style version is
|
|
faster than the generative one. Here is the accumulator template for a
|
|
structurally recursive version of <span class="RktSym"><a href="https://docs.racket-lang.org/teachpack/2htdpimage.html#%28def._%28%28lib._2htdp%2Fimage..rkt%29._rotate%29%29" class="RktValLink" data-pltdoc="x">rotate</a></span>:
|
|
<a name="(idx._(gentag._743))"></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">rotate.v2</span><span class="hspace"> </span><span class="RktSym">M0</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_two.html#%28tech._matrix%29" class="techoutside" data-pltdoc="x"><span class="techinside">Matrix</span></a><span class="RktCmt"> </span>...<span class="RktCmt"> -> </span><a href="part_two.html#%28tech._matrix%29" class="techoutside" data-pltdoc="x"><span class="techinside">Matrix</span></a><span class="RktCmt"> </span></td></tr><tr><td><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><span style="font-weight: bold">accumulator</span><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">rotate/a</span><span class="hspace"> </span><span class="RktSym">M</span><span class="hspace"> </span><span class="RktSym">seen</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="RktPn">(</span><span class="RktSym"><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">M</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><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">Can this be simplified to </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">M</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">rotate/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._rest%29%29" class="RktValLink" data-pltdoc="x">rest</a></span><span class="hspace"> </span><span class="RktSym">M</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="RktSym">seen</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="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><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">rotate/a</span><span class="hspace"> </span><span class="RktSym">M0</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">The goal is to remember the first row when its leading coefficient is
|
|
<span class="RktVal">0</span> without 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._append%29%29" class="RktValLink" data-pltdoc="x">append</a></span> for every recursion.</div></p><p>Formulate an accumulator statement. Then follow the accumulator design
|
|
recipe to complete the above function. Measure how fast it runs on a
|
|
<span class="RktSym">Matrix</span> that consists of rows with leading <span class="RktVal">0</span>s except for
|
|
the last one. If you completed the design correctly, the function is quite fast. <a href="part_six.html#%28counter._%28exercise._ex~3agauss-fast%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._(exercise._ex~3ato10))"></a><span style="font-weight: bold">Exercise</span> 504. Design <span class="RktSym">to10</span>. It consumes a list of digits and produces the
|
|
corresponding number. The first item on the list is the <span style="font-weight: bold">most significant</span>
|
|
digit. Hence, when applied to <span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">1</span><span class="stt"> </span><span class="RktVal">0</span><span class="stt"> </span><span class="RktVal">2</span><span class="RktVal">)</span>, it produces <span class="RktVal">102</span>.</p><p><span style="font-weight: bold">Domain Knowledge</span> You may recall from grade school that the result is determined by
|
|
<img src="pict_288.png" alt="image" width="299" height="13"/> <a href="part_six.html#%28counter._%28exercise._ex~3ato10%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._(exercise._ex~3ais-prime))"></a><span style="font-weight: bold">Exercise</span> 505. Design the function <span class="RktSym">is-prime</span>, which consumes a
|
|
natural number and returns <span class="RktVal">#true</span> if it is prime and <span class="RktVal">#false</span>
|
|
otherwise.</p><p><span style="font-weight: bold">Domain Knowledge</span> A number <span style="font-style: italic">n</span> is prime if it is not divisible by any
|
|
number between <span style="font-style: italic">n - </span>1<span style="font-style: italic"></span> and <span style="font-style: italic"></span>2<span style="font-style: italic"></span>.</p><p><div class="SIntrapara"><span style="font-weight: bold">Hint</span> The design recipe for <a href="part_two.html#%28tech._n%29" class="techoutside" data-pltdoc="x"><span class="techinside">N</span></a> [>=1] suggests the following template:
|
|
<a name="(idx._(gentag._744))"></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_two.html#%28tech._n%29" class="techoutside" data-pltdoc="x"><span class="techinside">N</span></a><span class="RktCmt"> [>=1] -> </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">determines whether </span><span class="RktSym">n</span><span class="RktCmt"> is a prime number</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">is-prime?</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._~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">1</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">is-prime?</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._sub1%29%29" class="RktValLink" data-pltdoc="x">sub1</a></span><span class="hspace"> </span><span class="RktSym">n</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><span class="RktPn">]</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">This template immediately tells you that the function forgets <span class="RktSym">n</span>, its
|
|
initial argument as it recurs. Since <span class="RktSym">n</span> is definitely needed to determine
|
|
whether <span class="RktSym">n</span> is divisible by <span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._-%29%29" class="RktValLink" data-pltdoc="x"><span class="nobreak">-</span></a></span><span class="stt"> </span><span class="RktSym">n</span><span class="stt"> </span><span class="RktVal">1</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._-%29%29" class="RktValLink" data-pltdoc="x"><span class="nobreak">-</span></a></span><span class="stt"> </span><span class="RktSym">n</span><span class="stt"> </span><span class="RktVal">2</span><span class="RktPn">)</span>, and so on,
|
|
you know that you need an accumulator-style function. <a href="part_six.html#%28counter._%28exercise._ex~3ais-prime%29%29" class="ex-end" data-pltdoc="x"></a></div></p><p><div class="SIntrapara"><span style="font-weight: bold">Note on Speed</span> Programmers who encounter accumulator-style functions for
|
|
the first time often get the impression that they are always faster than
|
|
their plain counterparts. So let’s take a look at the solution of
|
|
<a href="part_six.html#%28counter._%28exercise._ex~3atime-factorial%29%29" data-pltdoc="x">exercise 497</a>:<span class="refelem"><span class="refcolumn"><span class="refcontent">An explanation of these times is
|
|
beyond the scope of this book.</span></span></span>
|
|
</div><div class="SIntrapara"><blockquote><table cellspacing="0" cellpadding="0"><tr><td align="right"><p><span class="RktSym">!.v1</span></p></td><td align="right"><p><span class="hspace"> </span></p></td><td align="right"><p>5.760</p></td><td align="right"><p><span class="hspace"> </span></p></td><td align="right"><p>5.780</p></td><td align="right"><p><span class="hspace"> </span></p></td><td align="right"><p>5.800</p></td><td align="right"><p><span class="hspace"> </span></p></td><td align="right"><p>5.820</p></td><td align="right"><p><span class="hspace"> </span></p></td><td align="right"><p>5.870</p></td><td align="right"><p><span class="hspace"> </span></p></td><td align="right"><p><span class="highlighted"><span class="RktVal">5.806</span></span></p></td></tr><tr><td align="right"><p><span class="RktSym">!.v2</span></p></td><td align="right"><p><span class="hspace"> </span></p></td><td align="right"><p>5.970</p></td><td align="right"><p><span class="hspace"> </span></p></td><td align="right"><p>5.940</p></td><td align="right"><p><span class="hspace"> </span></p></td><td align="right"><p>5.980</p></td><td align="right"><p><span class="hspace"> </span></p></td><td align="right"><p>5.970</p></td><td align="right"><p><span class="hspace"> </span></p></td><td align="right"><p>6.690</p></td><td align="right"><p><span class="hspace"> </span></p></td><td align="right"><p><span class="highlighted"><span class="RktVal">6.111</span></span></p></td></tr></table></blockquote></div><div class="SIntrapara">The table’s top row shows the number of seconds for five runs of
|
|
<span class="RktPn">(</span><span class="RktSym">!.v1</span><span class="stt"> </span><span class="RktVal">20</span><span class="RktPn">)</span>, while the bottom one lists those of running
|
|
<span class="RktPn">(</span><span class="RktSym">!.v2</span><span class="stt"> </span><span class="RktVal">20</span><span class="RktPn">)</span>. The last column shows the averages. In short, the table
|
|
shows that people jump to premature conclusions; the performance of at
|
|
least one accumulator-style function is worse than that of the
|
|
original. <span style="font-weight: bold">Do not trust prejudices.</span> Instead, measure performance
|
|
characteristics of your programs for yourself. <span style="font-weight: bold">End</span></div></p><p><a name="(counter._(exercise._ex~3amap-accu))"></a><span style="font-weight: bold">Exercise</span> 506. Design an accumulator-style version 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 href="part_six.html#%28counter._%28exercise._ex~3amap-accu%29%29" class="ex-end" data-pltdoc="x"></a></p><p><div class="SIntrapara"><a name="(counter._(exercise._ex~3afoldl-designed))"></a><span style="font-weight: bold">Exercise</span> 507. <a href="part_three.html#%28counter._%28exercise._ex~3adesigning-build-list%29%29" data-pltdoc="x">Exercise 257</a> explains how
|
|
to design <span class="RktSym"><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> with the design recipes and guidelines of the
|
|
first two parts of the book: <a name="(idx._(gentag._745))"></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._check-expect%29%29" class="RktStxLink" data-pltdoc="x">check-expect</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">f*ldl</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._%2B%29%29" class="RktValLink" data-pltdoc="x">+</a></span><span class="hspace"> </span><span class="RktVal">0</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</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="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._foldl%29%29" class="RktValLink" data-pltdoc="x">foldl</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._%2B%29%29" class="RktValLink" data-pltdoc="x">+</a></span><span class="hspace"> </span><span class="RktVal">0</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</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="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">f*ldl</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._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></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="hspace"> </span><span class="RktVal">c</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._foldl%29%29" class="RktValLink" data-pltdoc="x">foldl</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._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></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="hspace"> </span><span class="RktVal">c</span><span class="RktVal">)</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">version 1</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">f*ldl</span><span class="hspace"> </span><span class="RktSym">f</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">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._foldr%29%29" class="RktValLink" data-pltdoc="x">foldr</a></span><span class="hspace"> </span><span class="RktSym">f</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="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._reverse%29%29" class="RktValLink" data-pltdoc="x">reverse</a></span><span class="hspace"> </span><span class="RktSym">l</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">That is, <span class="RktSym"><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> is the result of reversing the given list and then
|
|
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> to fold the given function over this intermediate list.</div></p><p><div class="SIntrapara">The <span class="RktSym">f*ldl</span> function obviously traverses the list twice, but once
|
|
we design all the functions, it becomes clear how much harder it has to work:
|
|
</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">version 2</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">f*ldl</span><span class="hspace"> </span><span class="RktSym">f</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">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#%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="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._reverse%29%29" class="RktValLink" data-pltdoc="x">reverse</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#%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">l</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><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">add-to-end</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">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._reverse%29%29" class="RktValLink" data-pltdoc="x">reverse</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._rest%29%29" class="RktValLink" data-pltdoc="x">rest</a></span><span class="hspace"> </span><span class="RktSym">l</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><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">add-to-end</span><span class="hspace"> </span><span class="RktSym">x</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#%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">l</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="RktSym">x</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"><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">l</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">add-to-end</span><span class="hspace"> </span><span class="RktSym">x</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">l</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><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"><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">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#%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">l</span><span class="RktPn">)</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="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">f</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">l</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._foldr%29%29" class="RktValLink" data-pltdoc="x">foldr</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._rest%29%29" class="RktValLink" data-pltdoc="x">rest</a></span><span class="hspace"> </span><span class="RktSym">l</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><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="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._reverse%29%29" class="RktValLink" data-pltdoc="x">reverse</a></span><span class="hspace"> </span><span class="RktSym">l</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">We know 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._reverse%29%29" class="RktValLink" data-pltdoc="x">reverse</a></span> has to traverse a list once for
|
|
every item on the list, meaning <span class="RktSym">f*ldl</span> really performs
|
|
<img src="pict_289.png" alt="image" width="12" height="10"/> traversals for a list of length <span style="font-style: italic">n</span>. Fortunately, we
|
|
know how to eliminate this bottleneck with an accumulator:
|
|
<a name="(idx._(gentag._746))"></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">version 3</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">f*ldl</span><span class="hspace"> </span><span class="RktSym">f</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">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#%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="RktPn">(</span><span class="RktSym">invert/a</span><span class="hspace"> </span><span class="RktSym">l</span><span class="hspace"> </span><span class="RktSym">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._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">l</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">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">invert/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._rest%29%29" class="RktValLink" data-pltdoc="x">rest</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._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">l</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">a</span><span class="RktPn">)</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="RktPn">(</span><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/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">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#%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">l</span><span class="RktPn">)</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="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">f</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">l</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._foldr%29%29" class="RktValLink" data-pltdoc="x">foldr</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._rest%29%29" class="RktValLink" data-pltdoc="x">rest</a></span><span class="hspace"> </span><span class="RktSym">l</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><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="RktPn">(</span><span class="RktSym">invert/a</span><span class="hspace"> </span><span class="RktSym">l</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></table></blockquote></div></p><p><div class="SIntrapara">Once <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._reverse%29%29" class="RktValLink" data-pltdoc="x">reverse</a></span> uses an accumulator, we actually get the apparent
|
|
performance of two traversals of the list. The question is whether we can
|
|
improve on this by adding an accumulator to the locally defined
|
|
<span class="RktSym">fold</span>:
|
|
</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">version 4</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">f*ldl</span><span class="hspace"> </span><span class="RktSym">f</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">l0</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="RktPn">(</span><span class="RktSym">fold/a</span><span class="hspace"> </span><span class="RktSym">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#%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">l</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">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">fold/a</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">f</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">l</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">a</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">l</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><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">fold/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._e%29%29" class="RktValLink" data-pltdoc="x">e</a></span><span class="hspace"> </span><span class="RktSym">l0</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">Since equipping the function with an accumulator reverses the order in
|
|
which the list is traversed, the initial reversal of the list is
|
|
superfluous.</div></p><p><div class="SIntrapara"><span style="font-weight: bold">Task 1</span> Recall the signature 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._foldl%29%29" class="RktValLink" data-pltdoc="x">foldl</a></span>:
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">[X Y] [X Y -> Y] Y [</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"> X] -> Y</span></p></blockquote></div><div class="SIntrapara">It is also the signature of <span class="RktSym">f*ldl</span>. Formulate the signature for
|
|
<span class="RktSym">fold/a</span> and its accumulator invariant. <span style="font-weight: bold">Hint</span> Assume that the
|
|
difference between <span class="RktSym">l0</span> and <span class="RktSym">l</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="RktSym">x1</span><span class="stt"> </span><span class="RktSym">x2</span><span class="stt"> </span><span class="RktSym">x3</span><span class="RktPn">)</span>. What is <span class="RktSym">a</span>, then?</div></p><p><div class="SIntrapara">You may also be wondering why <span class="RktSym">fold/a</span> consumes its arguments in
|
|
this unusual order, first the accumulator and then the list. To understand
|
|
the reason for this ordering, imagine instead that <span class="RktSym">fold/a</span> also
|
|
consumes <span class="RktSym">f</span>—<wbr></wbr>as the first argument. At this point it becomes
|
|
abundantly clear that <span class="RktSym">fold/a</span> is <span class="RktSym"><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>:
|
|
</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">version 5</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">f*ldl</span><span class="hspace"> </span><span class="RktSym">f</span><span class="hspace"> </span><span class="RktSym">i</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#%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">l</span><span class="RktPn">)</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._else%29%29" class="RktStxLink" data-pltdoc="x">else</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">f*ldl</span><span class="hspace"> </span><span class="RktSym">f</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">f</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">l</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">i</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">l</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><div class="SIntrapara"><span style="font-weight: bold">Task 2</span> Design <span class="RktSym">build-l*st</span> using an accumulator-style
|
|
approach. The function must satisfy the following tests:
|
|
</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">build-l*st</span><span class="hspace"> </span><span class="RktSym">n</span><span class="hspace"> </span><span class="RktSym">f</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._build-list%29%29" class="RktValLink" data-pltdoc="x">build-list</a></span><span class="hspace"> </span><span class="RktSym">n</span><span class="hspace"> </span><span class="RktSym">f</span><span class="RktPn">)</span><span class="RktPn">)</span></p></blockquote></div><div class="SIntrapara">for any natural number <span class="RktSym">n</span> and function <span class="RktSym">f</span>. <a href="part_six.html#%28counter._%28exercise._ex~3afoldl-designed%29%29" class="ex-end" data-pltdoc="x"></a></div></p><h4>32.4<tt> </tt><a name="(part._accu-edit._sec~3aedit3)"></a>A Graphical Editor, with Mouse</h4><p><a href="part_one.html#%28part._sec~3aedit1%29" data-pltdoc="x">A Graphical Editor</a> introduces the notion of a one-line editor and presents
|
|
a number of exercises on creating a graphical editor. Recall that a
|
|
graphical editor is an interactive program that interprets key events as
|
|
editing actions on a string. In particular, when a user presses the left or
|
|
right arrow keys, the cursor moves left or right; similarly, pressing the
|
|
delete key removes a <a href="part_one.html#%28tech._1string%29" class="techoutside" data-pltdoc="x"><span class="techinside">1String</span></a> from the edited text. The editor
|
|
program uses a <a name="(idx._accu-edit._(gentag._747._accu-edit))"></a>data representation that combines two strings in a
|
|
structure. <a href="part_two.html#%28part._list-edit2._sec~3aedit2%29" data-pltdoc="x">A Graphical Editor, Revisited</a> resumes these
|
|
exercises and shows how the same program can greatly benefit from a
|
|
different data structure, one that combines two strings.</p><p>Neither of these sections deals with mouse actions for navigation, even
|
|
though all modern applications support this functionality. The basic
|
|
difficulty with mouse events is to place the cursor at the appropriate
|
|
spot. Since the program deals with a single line of text, a mouse click at
|
|
<span style="font-style: italic"></span>(<span style="font-style: italic">x,y</span>)<span style="font-style: italic"></span> clearly aims to place the cursor between the letters that are
|
|
visible at or around the <span style="font-style: italic">x</span> position. This section fills the gap.</p><p>Recall the relevant definitions from <a href="part_two.html#%28part._list-edit2._sec~3aedit2%29" data-pltdoc="x">A Graphical Editor, Revisited</a>:
|
|
<a name="(idx._accu-edit._(gentag._748._accu-edit))"></a></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._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">FONT-SIZE</span><span class="hspace"> </span><span class="RktVal">11</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">FONT-COLOR</span><span class="hspace"> </span><span class="RktVal">"black"</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._1string%29" class="techoutside" data-pltdoc="x"><span class="techinside">1String</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">renders a string as an image for the editor </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">editor-text</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/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="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._implode%29%29" class="RktValLink" data-pltdoc="x">implode</a></span><span class="hspace"> </span><span class="RktSym">s</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">FONT-SIZE</span><span class="hspace"> </span><span class="RktSym">FONT-COLOR</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">editor</span><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym">pre</span><span class="hspace"> </span><span class="RktSym">post</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._accu-edit._editor)"></a><span style="font-style: italic">Editor</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-editor</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_one.html#%28tech._1string%29" class="techoutside" data-pltdoc="x"><span class="techinside">1String</span></a><span class="RktPn">]</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_one.html#%28tech._1string%29" class="techoutside" data-pltdoc="x"><span class="techinside">1String</span></a><span class="RktPn">]</span><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"> if </span><span class="RktPn">(</span><span class="RktSym">make-editor</span><span class="stt"> </span><span class="RktSym">p</span><span class="stt"> </span><span class="RktSym">s</span><span class="RktPn">)</span><span class="RktCmt"> is the state of </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">an interactive editor, </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._reverse%29%29" class="RktValLink" data-pltdoc="x">reverse</a></span><span class="stt"> </span><span class="RktSym">p</span><span class="RktPn">)</span><span class="RktCmt"> corresponds to</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">the text to the left of the cursor and </span><span class="RktSym">s</span><span class="RktCmt"> to the</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">text on the right </span></td></tr></table></blockquote><p><div class="SIntrapara"><a name="(counter._accu-edit._(exercise._ex~3aeditor-mouse-structural))"></a><span style="font-weight: bold">Exercise</span> 508. Design <span class="RktSym">split-structural</span>
|
|
using the structural design recipe. The function consumes a list of
|
|
<a href="part_one.html#%28tech._1string%29" class="techoutside" data-pltdoc="x"><span class="techinside">1String</span></a>s <span class="RktSym">ed</span> and a natural number <span class="RktSym">x</span>; the former
|
|
represents the complete string in some <a href="part_six.html#%28tech._accu-edit._editor%29" class="techoutside" data-pltdoc="x"><span class="techinside">Editor</span></a> and the latter the
|
|
x-coordinate of the mouse click. The function produces
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktPn">(</span><span class="RktSym">make-editor</span><span class="hspace"> </span><span class="RktSym">p</span><span class="hspace"> </span><span class="RktSym">s</span><span class="RktPn">)</span></p></blockquote></div><div class="SIntrapara">such that (1) <span class="RktSym">p</span> and <span class="RktSym">s</span> make up <span class="RktSym">ed</span> and (2) <span style="font-style: italic">x</span>
|
|
is larger than the image of <span class="RktSym">p</span> and smaller than the image of
|
|
<span class="RktSym">p</span> extended with the first <a href="part_one.html#%28tech._1string%29" class="techoutside" data-pltdoc="x"><span class="techinside">1String</span></a> on <span class="RktSym">s</span> (if any).</div></p><p><div class="SIntrapara">Here is the first condition expressed with an ISL+ expression:
|
|
</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._string~3d~3f%29%29" class="RktValLink" data-pltdoc="x">string=?</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-append%29%29" class="RktValLink" data-pltdoc="x">string-append</a></span><span class="hspace"> </span><span class="RktSym">p</span><span class="hspace"> </span><span class="RktSym">s</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">ed</span><span class="RktPn">)</span></p></blockquote></div><div class="SIntrapara">The second one is
|
|
</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._~3c~3d%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/teachpack/2htdpimage.html#%28def._%28%28lib._2htdp%2Fimage..rkt%29._image-width%29%29" class="RktValLink" data-pltdoc="x">image-width</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">editor-text</span><span class="hspace"> </span><span class="RktSym">p</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktSym">x</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._image-width%29%29" class="RktValLink" data-pltdoc="x">image-width</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">editor-text</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._append%29%29" class="RktValLink" data-pltdoc="x">append</a></span><span class="hspace"> </span><span class="RktSym">p</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">s</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">assuming <span class="RktPn">(</span><span class="RktSym"><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">s</span><span class="RktPn">)</span>.</div></p><p><span style="font-weight: bold">Hints</span> (1) The x-coordinate measures the distance from the
|
|
left. Hence the function must check whether larger and larger prefixes of
|
|
<span class="RktSym">ed</span> fit into the given width. The first one that doesn’t fit
|
|
corresponds to the <span class="RktSym">pre</span> field of the desired <a href="part_six.html#%28tech._accu-edit._editor%29" class="techoutside" data-pltdoc="x"><span class="techinside">Editor</span></a>, the
|
|
remainder of <span class="RktSym">ed</span> to the <span class="RktSym">post</span> field.</p><p>(2) Designing this function calls for thoroughly developing examples and
|
|
tests. See <a href="part_one.html#%28part._ch~3aintervals-enums%29" data-pltdoc="x">Intervals, Enumerations, and Itemizations</a>. <a href="part_six.html#%28counter._accu-edit._%28exercise._ex~3aeditor-mouse-structural%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._accu-edit._(exercise._ex~3aeditor-mouse))"></a><span style="font-weight: bold">Exercise</span> 509. Design the function <span class="RktSym">split</span>. Use the
|
|
accumulator design recipe to improve on the result of
|
|
<a href="part_six.html#%28counter._accu-edit._%28exercise._ex~3aeditor-mouse-structural%29%29" data-pltdoc="x">exercise 508</a>. After all, the hints already point out
|
|
that when the function discovers the correct split point, it needs both
|
|
parts of the list, and one part is obviously lost due to recursion. <a href="part_six.html#%28counter._accu-edit._%28exercise._ex~3aeditor-mouse%29%29" class="ex-end" data-pltdoc="x"></a></p><p>Once you have solved this exercise, equip the <span class="RktSym">main</span> function of
|
|
<a href="part_two.html#%28part._list-edit2._sec~3aedit2%29" data-pltdoc="x">A Graphical Editor, Revisited</a> with a clause for mouse
|
|
clicks. As you experiment with moving the cursor via mouse clicks, you will
|
|
notice that it does not exactly behave like applications that you use on
|
|
your other devices—<wbr></wbr>even though <span class="RktSym">split</span> passes all its
|
|
tests.</p><p>Graphical programs, like editors, call for experimentation to come up with the
|
|
best “look and feel” experiences. In this case, your editor is too
|
|
simplistic with its placement of the cursor. After the applications on your
|
|
computer determine the split point, they also determine which letter
|
|
division is closer to the x-coordinate and place the cursor
|
|
there.</p><p><a name="(counter._accu-edit._(exercise._ex~3afmt))"></a><span style="font-weight: bold">Exercise</span> 510. Many operating systems come with the <span class="stt">fmt</span> program,
|
|
which can rearrange the words in a file so that all lines in the resulting
|
|
file have a maximal width. As a widely used program, <span class="stt">fmt</span> supports a
|
|
range of related functions. This exercise focuses on its core functionality.</p><p>Design the program <span class="RktSym">fmt</span>. It consumes a natural number <span class="RktSym">w</span>,
|
|
the name of an input file <span class="RktSym">in-f</span>, and the name of an output file
|
|
<span class="RktSym">out-f</span>—<wbr></wbr>in the same sense as <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> from
|
|
<span class="sroman">the <span class="Smaller"><span style="font-style: italic">2htdp/batch-io</span></span> teachpack</span>. Its purpose is to read all the words from the
|
|
<span class="RktSym">in-f</span>, to arrange these words in the given order into lines of
|
|
maximal width <span class="RktSym">w</span>, and to write these lines to <span class="RktSym">out-f</span>. <a href="part_six.html#%28counter._accu-edit._%28exercise._ex~3afmt%29%29" class="ex-end" data-pltdoc="x"></a></p><h3>33<tt> </tt><a name="(part._ch~3amore-accu)"></a>More Uses of Accumulation</h3><p>This chapter presents three more uses of accumulators. The first section
|
|
concerns the use of accumulators in conjunction with tree-processing
|
|
functions. It uses the compilation of ISL+ as an illustrative
|
|
example. The second section explains why we occasionally want accumulators
|
|
inside of data representations and how to go about placing them there. The
|
|
final section resumes the discussion of rendering fractals.</p><h4>33.1<tt> </tt><a name="(part._sec~3amore-accu-trees)"></a>Accumulators and Trees</h4><p>When you ask DrRacket to run an ISL+ program, it translates the program to
|
|
commands for your specific computer. This process is called
|
|
<span style="font-style: italic">compilation</span>, and the part of DrRacket that performs the task is
|
|
called a <span style="font-style: italic">compiler</span>. Before the compiler translates the ISL+
|
|
program, it checks that every variable is declared 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._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span>,
|
|
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._define-struct%29%29" class="RktStxLink" data-pltdoc="x">define-struct</a></span>, or 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._lambda%29%29" class="RktStxLink" data-pltdoc="x">lambda</a></span>.</p><p>Stop! Enter <span class="RktSym">x</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="stt"> </span><span class="RktPn">(</span><span class="RktSym">y</span><span class="RktPn">)</span><span class="stt"> </span><span class="RktSym">x</span><span class="RktPn">)</span>, and <span class="RktPn">(</span><span class="RktSym">x</span><span class="stt"> </span><span class="RktVal">5</span><span class="RktPn">)</span> as
|
|
complete ISL+ programs into DrRacket and ask it to run each. What do you
|
|
expect to see?</p><p><div class="SIntrapara">Let’s phrase this idea as a sample problem:
|
|
</div><div class="SIntrapara"><blockquote><p><div class="SIntrapara"><span style="font-weight: bold">Sample Problem</span> You have been hired to re-create a part of the ISL+
|
|
compiler. Specifically, your task deals with the following language
|
|
fragment, specified in the so-called grammar notation that many programming
|
|
language manuals use:<span class="refelem"><span class="refcolumn"><span class="refcontent">We use the Greek letter λ instead 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._lambda%29%29" class="RktStxLink" data-pltdoc="x">lambda</a></span> to signal that this exercise deals with ISL+ as an
|
|
object of study, not just a programming language.</span></span></span>
|
|
</div><div class="SIntrapara"><table cellspacing="0" cellpadding="0"><tr><td align="right" valign="baseline"><span class="hspace"> </span><span class="RktVar">expression</span></td><td align="left" valign="baseline"><span class="stt"> </span></td><td align="center" valign="baseline">=</td><td align="left" valign="baseline"><span class="stt"> </span></td><td align="left" valign="baseline"><span class="RktVar">variable</span></td></tr><tr><td align="right" valign="baseline"><span class="stt"> </span></td><td align="left" valign="baseline"><span class="stt"> </span></td><td align="center" valign="baseline">|</td><td align="left" valign="baseline"><span class="stt"> </span></td><td align="left" valign="baseline"><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~ce~bb%29%29" class="RktStxLink" data-pltdoc="x">λ</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktVar">variable</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVar">expression</span><span class="RktPn">)</span></td></tr><tr><td align="right" valign="baseline"><span class="stt"> </span></td><td align="left" valign="baseline"><span class="stt"> </span></td><td align="center" valign="baseline">|</td><td align="left" valign="baseline"><span class="stt"> </span></td><td align="left" valign="baseline"><span class="RktPn">(</span><span class="RktVar">expression</span><span class="hspace"> </span><span class="RktVar">expression</span><span class="RktPn">)</span></td></tr></table></div><div class="SIntrapara">Remember from intermezzo 1 that you can read the grammar
|
|
aloud replacing <span class="RktInBG"><span class="hspace"></span><span class="RktIn">=</span><span class="hspace"></span></span> with “is one of” and <span class="RktInBG"><span class="hspace"></span><span class="RktIn">|</span><span class="hspace"></span></span> with “or.”</div></p><p>Recall that <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~ce~bb%29%29" class="RktStxLink" data-pltdoc="x">λ</a></span> expressions are functions without names. They bind
|
|
their parameter in their body. Conversely, a variable occurrence is
|
|
declared by a surrounding <span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~ce~bb%29%29" class="RktStxLink" data-pltdoc="x">λ</a></span> that specifies the same name as a
|
|
parameter. You may wish to revisit <a href="i3-4.html" data-pltdoc="x">Intermezzo 3: Scope and Abstraction</a> because it deals with the
|
|
same issue from the perspective of a programmer. Look for the terms “binding
|
|
occurrence,” “bound occurrence,” and “free.”</p><p>Develop a data representation for the above language fragment; use symbols
|
|
to represent variables. Then design a function that replaces all undeclared
|
|
variables with <span class="RktVal">'</span><span class="RktVal">*undeclared</span>.</p></blockquote></div><div class="SIntrapara">This problem is representative of many steps in the translation process
|
|
and, at the same time, is a great case study for accumulator-style
|
|
functions.</div></p><p><div class="SIntrapara">Before we dive into the problem, let’s look at some examples in this
|
|
mini-language, recalling what we know about <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>:
|
|
</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#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~ce~bb%29%29" class="RktStxLink" data-pltdoc="x">λ</a></span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym">x</span><span class="RktPn">)</span><span class="stt"> </span><span class="RktSym">x</span><span class="RktPn">)</span> is the function that returns whatever it is given,
|
|
also known as the identity function;</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._~ce~bb%29%29" class="RktStxLink" data-pltdoc="x">λ</a></span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym">x</span><span class="RktPn">)</span><span class="stt"> </span><span class="RktSym">y</span><span class="RktPn">)</span> looks like a function that returns <span class="RktSym">y</span>
|
|
whenever it is given an argument, except that <span class="RktSym">y</span> isn’t declared;</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._~ce~bb%29%29" class="RktStxLink" data-pltdoc="x">λ</a></span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym">y</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#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~ce~bb%29%29" class="RktStxLink" data-pltdoc="x">λ</a></span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym">x</span><span class="RktPn">)</span><span class="stt"> </span><span class="RktSym">y</span><span class="RktPn">)</span><span class="RktPn">)</span> is a function that, when given some value
|
|
<span class="RktSym">v</span>, produces a function that always returns <span class="RktSym">v</span>;</p></li><li><p><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._~ce~bb%29%29" class="RktStxLink" data-pltdoc="x">λ</a></span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym">x</span><span class="RktPn">)</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#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~ce~bb%29%29" class="RktStxLink" data-pltdoc="x">λ</a></span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym">x</span><span class="RktPn">)</span><span class="stt"> </span><span class="RktSym">x</span><span class="RktPn">)</span><span class="RktPn">)</span> applies the identity function to itself;</p></li><li><p><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._~ce~bb%29%29" class="RktStxLink" data-pltdoc="x">λ</a></span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym">x</span><span class="RktPn">)</span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym">x</span><span class="stt"> </span><span class="RktSym">x</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#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~ce~bb%29%29" class="RktStxLink" data-pltdoc="x">λ</a></span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym">x</span><span class="RktPn">)</span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym">x</span><span class="stt"> </span><span class="RktSym">x</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span> is a short infinite loop; and</p></li><li><p><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#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~ce~bb%29%29" class="RktStxLink" data-pltdoc="x">λ</a></span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym">y</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#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~ce~bb%29%29" class="RktStxLink" data-pltdoc="x">λ</a></span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym">x</span><span class="RktPn">)</span><span class="stt"> </span><span class="RktSym">y</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#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~ce~bb%29%29" class="RktStxLink" data-pltdoc="x">λ</a></span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym">z</span><span class="RktPn">)</span><span class="stt"> </span><span class="RktSym">z</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#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~ce~bb%29%29" class="RktStxLink" data-pltdoc="x">λ</a></span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym">w</span><span class="RktPn">)</span><span class="stt"> </span><span class="RktSym">w</span><span class="RktPn">)</span><span class="RktPn">)</span> is a complex
|
|
expression that is best run in ISL+ to find out whether it terminates.</p></li></ul></div><div class="SIntrapara">Indeed, you can run all of the above ISL+ expressions in DrRacket to confirm
|
|
what is written about them.</div></p><p><a name="(counter._(exercise._ex~3abinding1))"></a><span style="font-weight: bold">Exercise</span> 511. Explain the scope of each binding occurrence in
|
|
the above examples. Draw arrows from the bound to the binding occurrences. <a href="part_six.html#%28counter._%28exercise._ex~3abinding1%29%29" class="ex-end" data-pltdoc="x"></a></p><p><div class="SIntrapara">Developing a data representation for the language is easy, especially
|
|
because its description uses a grammar notation. Here is one possibility:
|
|
</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._lam)"></a><span style="font-style: italic">Lam</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"> a </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"><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">'</span><span class="RktVal">λ</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._list%29%29" class="RktValLink" data-pltdoc="x">list</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="RktPn">)</span><span class="stt"> </span><a href="part_six.html#%28tech._lam%29" class="techoutside" data-pltdoc="x"><span class="techinside">Lam</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._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="stt"> </span><a href="part_six.html#%28tech._lam%29" class="techoutside" data-pltdoc="x"><span class="techinside">Lam</span></a><span class="stt"> </span><a href="part_six.html#%28tech._lam%29" class="techoutside" data-pltdoc="x"><span class="techinside">Lam</span></a><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">Because 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>, this data representation makes it easy to
|
|
create data representations for expressions in our subset of ISL+:
|
|
</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">ex1</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">x</span><span class="RktVal">)</span><span class="hspace"> </span><span class="RktVal">x</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">ex2</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">x</span><span class="RktVal">)</span><span class="hspace"> </span><span class="RktVal">y</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">ex3</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">y</span><span class="RktVal">)</span><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">λ</span><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">x</span><span class="RktVal">)</span><span class="hspace"> </span><span class="RktVal">y</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">ex4</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">(</span><span class="RktVal">λ</span><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">x</span><span class="RktVal">)</span><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">x</span><span class="hspace"> </span><span class="RktVal">x</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">(</span><span class="RktVal">x</span><span class="RktVal">)</span><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">x</span><span class="hspace"> </span><span class="RktVal">x</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">These four data examples are representations of some of the above
|
|
expressions. Stop! Create data representations for the remaining examples.</div></p><p><a name="(counter._(exercise._ex~3afree-bound-access))"></a><span style="font-weight: bold">Exercise</span> 512. Define <span class="RktSym">is-var?</span>, <span class="RktSym">is-λ?</span>,
|
|
and <span class="RktSym">is-app?</span>, that is, predicates that distinguish variables from λ expressions and applications.</p><p><div class="SIntrapara">Also define
|
|
</div><div class="SIntrapara"><ul><li><p><span class="RktSym">λ-para</span>, which extracts the parameter from a λ expression;</p></li><li><p><span class="RktSym">λ-body</span>, which extracts the body from a λ expression;</p></li><li><p><span class="RktSym">app-fun</span>, which extracts the function from an application; and</p></li><li><p><span class="RktSym">app-arg</span>, which extracts the argument from an application.</p></li></ul></div><div class="SIntrapara">With these predicates and selectors, you basically can act as if you had
|
|
defined a structure-oriented data representation.</div></p><p>Design <span class="RktSym">declareds</span>, which produces the list of all symbols used as λ
|
|
parameters in a λ term. Don’t worry about duplicate symbols. <a href="part_six.html#%28counter._%28exercise._ex~3afree-bound-access%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._(exercise._ex~3afree-bound-dd0))"></a><span style="font-weight: bold">Exercise</span> 513. Develop a data representation for the same
|
|
subset of ISL+ that uses structures instead of lists. Also provide data
|
|
representations for <span class="RktSym">ex1</span>, <span class="RktSym">ex2</span>, and <span class="RktSym">ex3</span> following
|
|
your data definition. <a href="part_six.html#%28counter._%28exercise._ex~3afree-bound-dd0%29%29" class="ex-end" data-pltdoc="x"></a></p><p><div class="SIntrapara">We follow the structural design recipe, and here is the product of
|
|
steps two and three: <a name="(idx._(gentag._749))"></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_six.html#%28tech._lam%29" class="techoutside" data-pltdoc="x"><span class="techinside">Lam</span></a><span class="RktCmt"> -> </span><a href="part_six.html#%28tech._lam%29" class="techoutside" data-pltdoc="x"><span class="techinside">Lam</span></a><span class="RktCmt"> </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">replaces all symbols </span><span class="RktSym">s</span><span class="RktCmt"> in </span><span class="RktSym">le</span><span class="RktCmt"> with </span><span class="RktVal">'</span><span class="RktVal">*undeclared</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">if they do not occur within the body of a λ </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">expression whose parameter is </span><span class="RktSym">s</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">undeclareds</span><span class="hspace"> </span><span class="RktSym">ex1</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">ex1</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">undeclareds</span><span class="hspace"> </span><span class="RktSym">ex2</span><span class="RktPn">)</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">x</span><span class="RktVal">)</span><span class="hspace"> </span><span class="RktVal">*undeclared</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">undeclareds</span><span class="hspace"> </span><span class="RktSym">ex3</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">ex3</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">undeclareds</span><span class="hspace"> </span><span class="RktSym">ex4</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">ex4</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">undeclareds</span><span class="hspace"> </span><span class="RktSym">le0</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktSym">le0</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">Note how we expect <span class="RktSym">undeclareds</span> to process <span class="RktSym">ex4</span> even though
|
|
the expression loops forever when run; compilers don’t run programs, they
|
|
read them and create others.</div></p><p><div class="SIntrapara">A close look at the purpose statement directly suggests that the function
|
|
needs an accumulator. This becomes even clearer when we inspect the
|
|
template for <span class="RktSym">undeclareds</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">undeclareds</span><span class="hspace"> </span><span class="RktSym">le</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">is-var?</span><span class="hspace"> </span><span class="RktSym">le</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">is-λ?</span><span class="hspace"> </span><span class="RktSym">le</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._......%29%29" class="RktStxLink" data-pltdoc="x">...</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">undeclareds</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">λ-body</span><span class="hspace"> </span><span class="RktSym">le</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><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym">is-app?</span><span class="hspace"> </span><span class="RktSym">le</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">undeclareds</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">app-fun</span><span class="hspace"> </span><span class="RktSym">le</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="hspace"> </span><span class="RktPn">(</span><span class="RktSym">undeclareds</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">app-arg</span><span class="hspace"> </span><span class="RktSym">le</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><span class="RktPn">]</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">When <span class="RktSym">undeclareds</span> recurs on the body of (the representation of) a λ
|
|
expression, it forgets <span class="RktPn">(</span><span class="RktSym">λ-para</span><span class="stt"> </span><span class="RktSym">le</span><span class="RktPn">)</span>, the declared variable.</div></p><p><div class="SIntrapara">So, let’s start with an accumulator-style 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">undeclareds</span><span class="hspace"> </span><span class="RktSym">le0</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></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_six.html#%28tech._lam%29" class="techoutside" data-pltdoc="x"><span class="techinside">Lam</span></a><span class="RktCmt"> ??? -> </span><a href="part_six.html#%28tech._lam%29" class="techoutside" data-pltdoc="x"><span class="techinside">Lam</span></a></td></tr><tr><td><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><span style="font-weight: bold">accumulator</span><span class="RktCmt"> </span><span class="RktSym">a</span><span class="RktCmt"> represents ... </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">undeclareds/a</span><span class="hspace"> </span><span class="RktSym">le</span><span class="hspace"> </span><span class="RktSym">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._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">is-var?</span><span class="hspace"> </span><span class="RktSym">le</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">is-λ?</span><span class="hspace"> </span><span class="RktSym">le</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">undeclareds/a</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">λ-body</span><span class="hspace"> </span><span class="RktSym">le</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="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><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="RktPn">(</span><span class="RktSym">is-app?</span><span class="hspace"> </span><span class="RktSym">le</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">undeclareds/a</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">app-fun</span><span class="hspace"> </span><span class="RktSym">le</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="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></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">undeclareds/a</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">app-arg</span><span class="hspace"> </span><span class="RktSym">le</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="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><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><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">undeclareds/a</span><span class="hspace"> </span><span class="RktSym">le0</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">In this context, we can now formulate an accumulator invariant:
|
|
</div><div class="SIntrapara"><blockquote><p><span class="RktSym">a</span> represents the list of λ parameters encountered on the path from
|
|
the top of <span class="RktSym">le0</span> to the top of <span class="RktSym">le</span>.</p></blockquote></div><div class="SIntrapara">For example, if <span class="RktSym">le0</span> is
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">(</span><span class="RktVal">(</span><span class="RktVal">λ</span><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">y</span><span class="RktVal">)</span><span class="hspace"> </span><span class="highlighted"><span class="RktPn">(</span><span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~ce~bb%29%29" class="RktStxLink" data-pltdoc="x">λ</a></span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym">x</span><span class="RktPn">)</span><span class="stt"> </span><span class="RktSym">y</span><span class="RktPn">)</span></span><span class="RktVal">)</span><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">λ</span><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">z</span><span class="RktVal">)</span><span class="hspace"> </span><span class="RktVal">z</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">(</span><span class="RktVal">w</span><span class="RktVal">)</span><span class="hspace"> </span><span class="RktVal">w</span><span class="RktVal">)</span><span class="RktVal">)</span></p></blockquote></div><div class="SIntrapara">and <span class="RktSym">le</span> is the highlighted subtree, then <span class="RktSym">a</span> contains
|
|
<span class="RktSym">y</span>. The left side of <a href="part_six.html#%28counter._%28figure._fig~3alam-tree%29%29" data-pltdoc="x">figure <span class="FigureRef">186</span></a> presents a graphical
|
|
illustration of the same example. It shows a <a href="part_six.html#%28tech._lam%29" class="techoutside" data-pltdoc="x"><span class="techinside">Lam</span></a> expression as an
|
|
upside-down tree; that is, the root is at the top. A <span class="stt">@</span> node represents
|
|
an application with two descendants; the other nodes are
|
|
self-explanatory. In this tree diagram, the bold path leads from
|
|
<span class="RktSym">le0</span> to <span class="RktSym">le</span> through a single variable declaration.</div></p><p><div class="SIntrapara">Similarly, if we pick a different subtree of the same piece of data,
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">(</span><span class="RktVal">(</span><span class="RktVal">λ</span><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">y</span><span class="RktVal">)</span><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">λ</span><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">x</span><span class="RktVal">)</span><span class="hspace"> </span><span class="highlighted"><span class="RktSym">y</span></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">(</span><span class="RktVal">z</span><span class="RktVal">)</span><span class="hspace"> </span><span class="RktVal">z</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">(</span><span class="RktVal">w</span><span class="RktVal">)</span><span class="hspace"> </span><span class="RktVal">w</span><span class="RktVal">)</span><span class="RktVal">)</span></p></blockquote></div><div class="SIntrapara">we get an accumulator that contains both <span class="RktVal">'</span><span class="RktVal">y</span> and <span class="RktVal">'</span><span class="RktVal">x</span>.
|
|
The right side of <a href="part_six.html#%28counter._%28figure._fig~3alam-tree%29%29" data-pltdoc="x">figure <span class="FigureRef">186</span></a> makes this point again. Here
|
|
the bold path leads through two <span class="RktVal">'</span><span class="RktVal">λ</span> nodes to the boxed subtree,
|
|
and the accumulator is the list of declared variables along the bold
|
|
path.</div></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_290.png" alt="image" width="194.0" height="326.0"/>
|
|
<span class="hspace"> </span>
|
|
<img style="vertical-align: -0.0px; margin: -3px -3px -3px -3px;" src="pict_291.png" alt="image" width="194.0" height="326.0"/></p></blockquote></blockquote></blockquote><p class="Centertext"><span class="Legend"><span class="FigureTarget"><a name="(counter._(figure._fig~3alam-tree))" x-target-lift="Figure"></a>Figure 186: </span><a href="part_six.html#%28tech._lam%29" class="techoutside" data-pltdoc="x"><span class="techinside">Lam</span></a> terms as trees</span></p></blockquote><p><div class="SIntrapara">Now that we have settled on the data representation of the accumulator and
|
|
its invariant, we can resolve the remaining design questions:
|
|
</div><div class="SIntrapara"><ul><li><p>We pick an initial accumulator value of <span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span>.</p></li><li><p>We 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> to add <span class="RktPn">(</span><span class="RktSym">λ-para</span><span class="stt"> </span><span class="RktSym">le</span><span class="RktPn">)</span> to <span class="RktSym">a</span>.</p></li><li><p>We exploit the accumulator for the clause where
|
|
<span class="RktSym">undeclareds/a</span> deals with a variable. Specifically, the function
|
|
uses the accumulator to check whether the variable is in the scope of a
|
|
declaration.</p></li></ul></div></p><p><a href="part_six.html#%28counter._%28figure._fig~3aundeclareds%29%29" data-pltdoc="x">Figure <span class="FigureRef">187</span></a> shows how to translate these ideas into a
|
|
complete function definition. Note the name <span class="RktSym">declareds</span> for the
|
|
accumulator; it brings across the key idea behind the accumulator
|
|
invariant, helping the programmer understand the definition. The base case
|
|
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._member~3f%29%29" class="RktValLink" data-pltdoc="x">member?</a></span> from ISL+ to determine whether the variable
|
|
<span class="RktSym">le</span> is in <span class="RktSym">declareds</span> and, if not, replaces it with
|
|
<span class="RktVal">'</span><span class="RktVal">*undeclared</span>. 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 uses 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> to introduce the extended accumulator <span class="RktSym">newd</span>. Because
|
|
<span class="RktSym">para</span> is also used to rebuild the expression, it has its own
|
|
local definition. Finally, the last clause concerns function applications,
|
|
which do not declare variables and do not use any directly. As a result,
|
|
it is by far the simplest of the three clauses.</p><p><div class="SIntrapara"><a name="(idx._(gentag._750))"></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_six.html#%28tech._lam%29" class="techoutside" data-pltdoc="x"><span class="techinside">Lam</span></a><span class="RktCmt"> -> </span><a href="part_six.html#%28tech._lam%29" class="techoutside" data-pltdoc="x"><span class="techinside">Lam</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">undeclareds</span><span class="hspace"> </span><span class="RktSym">le0</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_six.html#%28tech._lam%29" class="techoutside" data-pltdoc="x"><span class="techinside">Lam</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="i2-3.html#%28tech._symbol%29" class="techoutside" data-pltdoc="x"><span class="techinside">Symbol</span></a><span class="RktCmt">] -> </span><a href="part_six.html#%28tech._lam%29" class="techoutside" data-pltdoc="x"><span class="techinside">Lam</span></a></td></tr><tr><td><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><span style="font-weight: bold">accumulator</span><span class="RktCmt"> </span><span class="RktSym">declareds</span><span class="RktCmt"> is a list of all λ </span></td></tr><tr><td><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">parameters on the path from </span><span class="RktSym">le0</span><span class="RktCmt"> to </span><span class="RktSym">le</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">undeclareds/a</span><span class="hspace"> </span><span class="RktSym">le</span><span class="hspace"> </span><span class="RktSym">declareds</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">is-var?</span><span class="hspace"> </span><span class="RktSym">le</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._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._member~3f%29%29" class="RktValLink" data-pltdoc="x">member?</a></span><span class="hspace"> </span><span class="RktSym">le</span><span class="hspace"> </span><span class="RktSym">declareds</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">le</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">*undeclared</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">is-λ?</span><span class="hspace"> </span><span class="RktSym">le</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">para</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">λ-para</span><span class="hspace"> </span><span class="RktSym">le</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">body</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">λ-body</span><span class="hspace"> </span><span class="RktSym">le</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">newd</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="RktSym">para</span><span class="hspace"> </span><span class="RktSym">declareds</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._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">λ</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">para</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">undeclareds/a</span><span class="hspace"> </span><span class="RktSym">body</span><span class="hspace"> </span><span class="RktSym">newd</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="RktPn">[</span><span class="RktPn">(</span><span class="RktSym">is-app?</span><span class="hspace"> </span><span class="RktSym">le</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">fun</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">app-fun</span><span class="hspace"> </span><span class="RktSym">le</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">arg</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">app-arg</span><span class="hspace"> </span><span class="RktSym">le</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._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">undeclareds/a</span><span class="hspace"> </span><span class="RktSym">fun</span><span class="hspace"> </span><span class="RktSym">declareds</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">undeclareds/a</span><span class="hspace"> </span><span class="RktSym">arg</span><span class="hspace"> </span><span class="RktSym">declareds</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><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">undeclareds/a</span><span class="hspace"> </span><span class="RktSym">le0</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></table></blockquote></blockquote><p class="Centertext"><span class="Legend"><span class="FigureTarget"><a name="(counter._(figure._fig~3aundeclareds))" x-target-lift="Figure"></a>Figure 187: </span>Finding undeclared variables</span></p></blockquote></div></p><p><a name="(counter._(exercise._ex~3afree-bound-both))"></a><span style="font-weight: bold">Exercise</span> 514. Make up an ISL+ expression in which
|
|
<span class="RktSym">x</span> occurs both free and bound. Formulate it as an element of
|
|
<a href="part_six.html#%28tech._lam%29" class="techoutside" data-pltdoc="x"><span class="techinside">Lam</span></a>. Does <span class="RktSym">undeclareds</span> work properly on your expression? <a href="part_six.html#%28counter._%28exercise._ex~3afree-bound-both%29%29" class="ex-end" data-pltdoc="x"></a></p><p><div class="SIntrapara"><a name="(counter._(exercise._ex~3afree-bound-undeclared))"></a><span style="font-weight: bold">Exercise</span> 515. Consider the following expression:
|
|
</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._~ce~bb%29%29" class="RktStxLink" data-pltdoc="x">λ</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">*undeclared</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#%28form._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._~ce~bb%29%29" class="RktStxLink" data-pltdoc="x">λ</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">x</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">x</span><span class="hspace"> </span><span class="RktSym">*undeclared</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">y</span><span class="RktPn">)</span><span class="RktPn">)</span></p></blockquote></div><div class="SIntrapara">Yes, it uses <span class="RktSym">*undeclared</span> as a variable. Represent it in <a href="part_six.html#%28tech._lam%29" class="techoutside" data-pltdoc="x"><span class="techinside">Lam</span></a>
|
|
and check what <span class="RktSym">undeclareds</span> produces for this expression.</div></p><p><div class="SIntrapara">Modify <span class="RktSym">undeclareds</span> so that it replaces a free occurrence of <span class="RktVal">'</span><span class="RktVal">x</span> with
|
|
</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">'</span><span class="RktVal">*undeclared</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">x</span><span class="RktPn">)</span></p></blockquote></div><div class="SIntrapara">and a bound one <span class="RktVal">'</span><span class="RktVal">y</span> with
|
|
</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">'</span><span class="RktVal">*declared</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">y</span><span class="RktPn">)</span></p></blockquote></div><div class="SIntrapara">Doing so unambiguously identifies problem spots, which a program development
|
|
environment such as DrRacket can use to highlight errors.</div></p><p><span style="font-weight: bold">Note</span> The trick of replacing a variable occurrence with the
|
|
representation of an application feels awkward. If you dislike it, consider
|
|
synthesizing the symbols <span class="RktVal">'</span><span class="RktVal">*undeclared:x</span> and <span class="RktVal">'</span><span class="RktVal">declared:y</span>
|
|
instead. <a href="part_six.html#%28counter._%28exercise._ex~3afree-bound-undeclared%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._(exercise._ex~3afree-bound-dd1))"></a><span style="font-weight: bold">Exercise</span> 516. Redesign the <span class="RktSym">undeclareds</span> function
|
|
for the structure-based data representation from
|
|
<a href="part_six.html#%28counter._%28exercise._ex~3afree-bound-dd0%29%29" data-pltdoc="x">exercise 513</a>. <a href="part_six.html#%28counter._%28exercise._ex~3afree-bound-dd1%29%29" class="ex-end" data-pltdoc="x"></a></p><p><div class="SIntrapara"><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_292.png" alt="image" width="280.0" height="432.0"/>
|
|
<span class="hspace"> </span>
|
|
<img style="vertical-align: -0.0px; margin: -3px -3px -3px -3px;" src="pict_293.png" alt="image" width="280.0" height="432.0"/></p></blockquote></blockquote></blockquote><p class="Centertext"><span class="Legend"><span class="FigureTarget"><a name="(counter._(figure._fig~3asd))" x-target-lift="Figure"></a>Figure 188: </span>Static distances</span></p></blockquote></div><div class="SIntrapara"><a name="(counter._(exercise._ex~3afree-bound1))"></a><span style="font-weight: bold">Exercise</span> 517. Design <span class="RktSym">static-distance</span>. The function
|
|
replaces all occurrences of variables with a natural number that represents
|
|
how far away the declaring λ is. <a href="part_six.html#%28counter._%28figure._fig~3asd%29%29" data-pltdoc="x">Figure <span class="FigureRef">188</span></a> illustrates the idea
|
|
for the term
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><p><span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">(</span><span class="RktVal">λ</span><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">x</span><span class="RktVal">)</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">y</span><span class="RktVal">)</span><span class="hspace"> </span><span class="RktVal">(</span><span class="RktVal">y</span><span class="hspace"> </span><span class="RktVal">x</span><span class="RktVal">)</span><span class="RktVal">)</span><span class="hspace"> </span><span class="RktVal">x</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">(</span><span class="RktVal">z</span><span class="RktVal">)</span><span class="hspace"> </span><span class="RktVal">z</span><span class="RktVal">)</span><span class="RktVal">)</span></p></blockquote></div><div class="SIntrapara">in graphical form. It includes dotted arrows that point from variable
|
|
occurrences to the corresponding variable declarations. On the right, the
|
|
figure shows a tree of the same shape, though without the arrows. The
|
|
<span class="RktVal">'</span><span class="RktVal">λ</span> nodes come without names, and variable occurrences have been
|
|
replaced by natural numbers that specify which <span class="RktVal">'</span><span class="RktVal">λ</span> declares the
|
|
variable. Each natural number <span class="RktSym">n</span> says that the binding occurrence
|
|
is <span class="RktSym">n</span> steps upward—<wbr></wbr>toward the root of the <a href="part_six.html#%28tech._lam%29" class="techoutside" data-pltdoc="x"><span class="techinside">Lam</span></a> tree. A
|
|
value of <span class="RktVal">0</span> denotes the first <span class="RktVal">'</span><span class="RktVal">λ</span> on the path to the root,
|
|
<span class="RktVal">1</span> the second one, and so on.</div></p><p><span style="font-weight: bold">Hint</span> The <span class="RktSym">undeclareds</span> accumulator of <span class="RktSym">undeclareds/a</span>
|
|
is a list of all parameters on path from <span class="RktSym">le</span> to <span class="RktSym">le0</span>
|
|
<span style="font-weight: bold">in reverse order</span>—<wbr></wbr>the last one seen is first on the list. <a href="part_six.html#%28counter._%28exercise._ex~3afree-bound1%29%29" class="ex-end" data-pltdoc="x"></a></p><h4>33.2<tt> </tt><a name="(part._sec~3amore-accu-mc)"></a>Data Representations with Accumulators</h4><p>The end of <a href="i5-6.html" data-pltdoc="x">Intermezzo 5: The Cost of Computation</a> explains that <span class="stt">*SL</span> measures the size of
|
|
containers, say lists, by traversing them and hints that other programming
|
|
languages use a different,<span class="refelem"><span class="refcolumn"><span class="refcontent">See <a href="part_two.html#%28part._sec~3asec-fsm-list%29" data-pltdoc="x">Finite State Machines</a> for
|
|
an early example of this idea.</span></span></span> less expensive way, to compute sizes. In
|
|
this section, we show how to implement this idea with the <span style="font-weight: bold">addition
|
|
of an accumulator to data representations</span>.</p><p>Consider the ubiquitous lists in <span class="stt">*SL</span>. All lists are constructed from
|
|
<span class="RktSym"><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> and <span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span>; operations such as <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> 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._list%29%29" class="RktValLink" data-pltdoc="x">list</a></span>, for example, are merely abbreviations for these two. As
|
|
<a href="part_two.html#%28part._sec~3alists-cons%29" data-pltdoc="x">What Is <span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span>, What Is <span class="RktSym"><span class="RktValLink">cons</span></span></a> shows, it is also possible to mimic lists in
|
|
BSL with suitable structure type and function definitions.</p><p><div class="SIntrapara"><a name="(idx._(gentag._751))"></a>
|
|
<a name="(idx._(gentag._752))"></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-struct%29%29" class="RktStxLink" data-pltdoc="x">define-struct</a></span><span class="hspace"> </span><span class="RktSym">pair</span><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym">left</span><span class="hspace"> </span><span class="RktSym">right</span><span class="RktPn">]</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span style="font-style: italic">ConsOrEmpty</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">make-pair</span><span class="stt"> </span><a href="part_one.html#%28tech._any%29" class="techoutside" data-pltdoc="x"><span class="techinside">Any</span></a><span class="stt"> </span><a href="part_two.html#%28tech._consorempty%29" class="techoutside" data-pltdoc="x"><span class="techinside">ConsOrEmpty</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._any%29" class="techoutside" data-pltdoc="x"><span class="techinside">Any</span></a><span class="RktCmt"> </span><a href="part_two.html#%28tech._consorempty%29" class="techoutside" data-pltdoc="x"><span class="techinside">ConsOrEmpty</span></a><span class="RktCmt"> -> </span><a href="part_two.html#%28tech._consorempty%29" class="techoutside" data-pltdoc="x"><span class="techinside">ConsOrEmpty</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">our-cons</span><span class="hspace"> </span><span class="RktSym">a-value</span><span class="hspace"> </span><span class="RktSym">a-list</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-list</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">make-pair</span><span class="hspace"> </span><span class="RktSym">a-value</span><span class="hspace"> </span><span class="RktSym">a-list</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">pair?</span><span class="hspace"> </span><span class="RktSym">a-list</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">make-pair</span><span class="hspace"> </span><span class="RktSym">a-value</span><span class="hspace"> </span><span class="RktSym">a-list</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"><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">"our-cons: ..."</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_two.html#%28tech._consorempty%29" class="techoutside" data-pltdoc="x"><span class="techinside">ConsOrEmpty</span></a><span class="RktCmt"> -> </span><a href="part_one.html#%28tech._any%29" class="techoutside" data-pltdoc="x"><span class="techinside">Any</span></a></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">extracts the </span><span class="RktSym">left</span><span class="RktCmt"> part of the given </span><span class="RktSym">pair</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">our-first</span><span class="hspace"> </span><span class="RktSym">mimicked-list</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._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._empty~3f%29%29" class="RktValLink" data-pltdoc="x">empty?</a></span><span class="hspace"> </span><span class="RktSym">mimicked-list</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">"our-first: ..."</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">pair-left</span><span class="hspace"> </span><span class="RktSym">mimicked-list</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></blockquote><p class="Centertext"><span class="Legend"><span class="FigureTarget"><a name="(counter._(figure._fig~3acons-recall))" x-target-lift="Figure"></a>Figure 189: </span>An implementation of lists in BSL</span></p></blockquote></div></p><p><a href="part_six.html#%28counter._%28figure._fig~3acons-recall%29%29" data-pltdoc="x">Figure <span class="FigureRef">189</span></a> recalls the basic idea. Stop! Can you define
|
|
<span class="RktSym">our-rest</span> now?</p><p><div class="SIntrapara">The key insight is that we can add a third field to the structure type
|
|
definition of <span class="RktSym">pair</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-struct%29%29" class="RktStxLink" data-pltdoc="x">define-struct</a></span><span class="hspace"> </span><span class="RktSym">cpair</span><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym">count</span><span class="hspace"> </span><span class="RktSym">left</span><span class="hspace"> </span><span class="RktSym">right</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._mylist)"></a><span style="font-style: italic">MyList</span><span class="RktCmt"> X] 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">make-cpair</span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym">tech</span><span class="stt"> </span><span class="RktVal">"N"</span><span class="RktPn">)</span><span class="stt"> </span><span class="RktSym">X</span><span class="stt"> </span><span class="RktPn">[</span><a href="part_six.html#%28tech._mylist%29" class="techoutside" data-pltdoc="x"><span class="techinside">MyList</span></a><span class="stt"> </span><span class="RktSym">X</span><span class="RktPn">]</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span style="font-weight: bold">accumulator</span><span class="RktCmt"> the </span><span class="RktSym">count</span><span class="RktCmt"> field is the number of </span><span class="RktSym">cpair</span><span class="RktCmt">s</span></td></tr></table></blockquote></div><div class="SIntrapara">As the accumulator statement says, the extra field is used to keep track
|
|
of the number of <span class="RktSym">cpair</span> instances used to create the list. That
|
|
is, it remembers a fact about the construction of the list. We
|
|
call this kind of structure field a <span style="font-style: italic">data accumulator</span>.</div></p><p><div class="SIntrapara">Adding a field to the major list constructor does not come for free. To
|
|
begin with, it requires a change to the checked version of the
|
|
constructor, the one that is actually available to programs: <a name="(idx._(gentag._753))"></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">data definitions, via a constructor-function </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">our-cons</span><span class="hspace"> </span><span class="RktSym">f</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#%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">r</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">make-cpair</span><span class="hspace"> </span><span class="RktVal">1</span><span class="hspace"> </span><span class="RktSym">f</span><span class="hspace"> </span><span class="RktSym">r</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">cpair?</span><span class="hspace"> </span><span class="RktSym">r</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">make-cpair</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._%2B%29%29" class="RktValLink" data-pltdoc="x">+</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">cpair-count</span><span class="hspace"> </span><span class="RktSym">r</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">1</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">f</span><span class="hspace"> </span><span class="RktSym">r</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"><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">"our-cons: ..."</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">If the extended list is <span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span>, <span class="RktSym">count</span> is populated with
|
|
<span class="RktVal">1</span>; otherwise, the function computes the length from the given
|
|
<span class="RktSym">cpair</span>.</div></p><p><div class="SIntrapara">Now the function definition for <span class="RktSym">our-length</span> is obvious: <a name="(idx._(gentag._754))"></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._any%29" class="techoutside" data-pltdoc="x"><span class="techinside">Any</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></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">how many items does </span><span class="RktSym">l</span><span class="RktCmt"> contain</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">our-length</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#%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">l</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktVal">0</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktPn">(</span><span class="RktSym">cpair?</span><span class="hspace"> </span><span class="RktSym">l</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">cpair-count</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#%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#%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">"my-length: ..."</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 function consumes any kind of value. For <span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span> and instances of
|
|
<span class="RktSym">cpair</span>, it produces natural numbers; otherwise it signals an
|
|
error.</div></p><p>The second problem with the addition of a <span class="RktSym">count</span> field concerns
|
|
performance. Indeed, there are two concerns. On the one hand, every single
|
|
list construction comes with an extra field now, meaning a 33% increase in
|
|
memory consumption. On the other hand, the addition of the field decreases
|
|
how fast <span class="RktSym">our-cons</span> constructs a list. In addition to the check
|
|
that the extended list is either <span class="RktVal">'</span><span class="RktVal">(</span><span class="RktVal">)</span> or an instance of a <span class="RktSym">cpair</span>,
|
|
the constructor now computes the size of the list. Although this
|
|
computation consumes a constant amount of time, it is imposed on every
|
|
single use of <span class="RktSym">our-cons</span>—<wbr></wbr>and just think how many times this book
|
|
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._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span> and does not ever compute how long the resulting list
|
|
is!</p><p><a name="(counter._(exercise._ex~3aconstant-time-length))"></a><span style="font-weight: bold">Exercise</span> 518. Argue that <span class="RktSym">our-cons</span> takes a
|
|
constant amount of time to compute its result, regardless of the size of
|
|
its input. <a href="part_six.html#%28counter._%28exercise._ex~3aconstant-time-length%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._(exercise._ex~3aextra-cost-cons))"></a><span style="font-weight: bold">Exercise</span> 519. Is it acceptable to impose the extra cost
|
|
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._cons%29%29" class="RktValLink" data-pltdoc="x">cons</a></span> for all programs to turn <span class="RktSym">length</span> into a
|
|
constant-time function? <a href="part_six.html#%28counter._%28exercise._ex~3aextra-cost-cons%29%29" class="ex-end" data-pltdoc="x"></a></p><p>While the addition of a <span class="RktSym">count</span> field to lists is questionable,
|
|
sometimes data accumulators play a crucial role in finding a solution. The
|
|
next example is about adding so-called <span style="font-style: italic">artificial intelligence</span>
|
|
to a board-game-playing program, and its data accumulator is an absolute
|
|
necessity.</p><p><div class="SIntrapara">As you play board games or solve puzzles, you tend to think about your
|
|
possible moves at every stage. As you get better, you may even imagine the
|
|
possibilities after this first step. The result is a so-called
|
|
<span style="font-style: italic">game tree</span>, which is a (part of the) tree of all possible moves
|
|
that the rules allow. Let’s start with a problem:
|
|
</div><div class="SIntrapara"><blockquote><p><span style="font-weight: bold">Sample Problem</span> Your manager tells you the following story.</p><p>“Once upon a time, three cannibals were guiding three missionaries through a
|
|
jungle. They were on their way to the nearest mission station. After some
|
|
time, they arrived at a wide river, filled with deadly snakes and
|
|
fish. There was no way to cross the river without a boat. Fortunately,
|
|
they found a rowboat with two oars after a short search. Unfortunately,
|
|
the boat was too small to carry all of them. It could barely carry two
|
|
people at a time. Worse, because of the river’s width someone had to
|
|
row the boat back.</p><p>“Since the missionaries could not trust the cannibals, they had to figure out
|
|
a plan to get all six of them safely across the river. The problem was
|
|
that these cannibals would kill and eat missionaries as soon as there were
|
|
more cannibals than missionaries in some place. Our
|
|
missionaries had to devise a plan that guaranteed that there were
|
|
never any missionaries in the minority on either side of the river. The
|
|
cannibals, however, could be trusted to cooperate otherwise. Specifically,
|
|
they would not abandon any potential food, just as the missionaries
|
|
would not abandon any potential converts.”</p><p>While your manager doesn’t assign any specific design task, he wants to
|
|
explore whether the company can design (and sell) programs that solve such
|
|
puzzles.</p></blockquote></div><div class="SIntrapara">While puzzles aren’t board games, the program illustrates the idea of game
|
|
trees in the most straightforward manner possible.</div></p><p><div class="SIntrapara">In principle, it is quite straightforward to solve such puzzles by
|
|
hand. Here is the rough idea. Pick a graphical representation of the
|
|
problem states. Ours consists of a three-part box: the left one represents
|
|
the missionaries and the cannibals; the middle combines the
|
|
river and the boat; and the third part is the right-hand side of the
|
|
river. Take a look at the following representation of the initial state:
|
|
</div><div class="SIntrapara"><blockquote class="SCentered"><p><img style="vertical-align: 0px; margin: -3px -3px -3px -3px;" src="pict_294.png" alt="image" width="114.24000000000001" height="49.56"/></p></blockquote></div><div class="SIntrapara">Black circles denote missionaries, white circles cannibals. All of them are
|
|
on the left-hand river bank. The boat is also on the left side. Nobody is
|
|
on the right. Here are two more states:
|
|
</div><div class="SIntrapara"><blockquote class="SCentered"><p><img style="vertical-align: 0px; margin: -3px -3px -3px -3px;" src="pict_295.png" alt="image" width="114.24000000000001" height="49.56"/>
|
|
<span class="hspace"> </span>
|
|
<img style="vertical-align: 0px; margin: -3px -3px -3px -3px;" src="pict_296.png" alt="image" width="114.24000000000001" height="49.56"/></p></blockquote></div><div class="SIntrapara">The first one is the final state, where all people and the boat are on the
|
|
right bank of the river. The second one depicts some intermediate state
|
|
where two people are on the left with the boat and four people are on the
|
|
right.</div></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_297.png" alt="image" width="530.72" height="353.8"/></p></blockquote></blockquote></blockquote><p class="Centertext"><span class="Legend"><span class="FigureTarget"><a name="(counter._(figure._fig~3amc-transition))" x-target-lift="Figure"></a>Figure 190: </span>Creating a game tree</span></p></blockquote><p>Now that you have a way to write down the state of the puzzle, you can
|
|
think about the possibilities at each stage. Doing so yields a tree of
|
|
possible moves. <a href="part_six.html#%28counter._%28figure._fig~3amc-transition%29%29" data-pltdoc="x">Figure <span class="FigureRef">190</span></a> sketches the first two and
|
|
a half layers in such a tree. The left-most state is the initial
|
|
one. Because the boat can transport at most two people and must be rowed
|
|
by at least one, you have five possibilities to explore: one cannibal rows
|
|
across; two cannibals row across; one missionary and one cannibal go; one
|
|
missionary crosses; or two missionaries do. These possibilities are
|
|
represented with five arrows going from the initial state to five
|
|
intermediate states.</p><p>For each of these five intermediate states, you can play the same game
|
|
again. In <a href="part_six.html#%28counter._%28figure._fig~3amc-transition%29%29" data-pltdoc="x">figure <span class="FigureRef">190</span></a> you see how the game continues
|
|
for the middle (third) one of the new states. Because there are only two
|
|
people on the right river bank, you see three possibilities: a cannibal
|
|
goes back, a missionary goes back, or both do. Hence three arrows connect
|
|
the middle state to the three states on the right side of the tree. If
|
|
you keep drawing this tree of possibilities in a systematic manner, you
|
|
eventually discover the final state.</p><p>A second look at <a href="part_six.html#%28counter._%28figure._fig~3amc-transition%29%29" data-pltdoc="x">figure <span class="FigureRef">190</span></a> reveals two problems with
|
|
this naive approach to generating the tree of possibilities. The first one
|
|
is the dashed arrow that connects the middle state on the right to the
|
|
initial state. It indicates that rowing back the two people from the right
|
|
to the left gets the puzzle back to its initial state, meaning you’re
|
|
starting over, which is obviously undesirable. The second problem concerns
|
|
those states with a star in the top-right corner. In both cases, there are
|
|
more white-circle cannibals than black-circle missionaries on the left
|
|
river bank, meaning the cannibals would eat the missionaries. Again, the
|
|
goal is to avoid such states, making these moves undesirable.</p><p><div class="SIntrapara">One way to turn this puzzle into a program is to design a function that
|
|
determines whether some final state—<wbr></wbr>here <span style="font-weight: bold">the</span> final state—<wbr></wbr>is
|
|
reachable from some given state. Here is an appropriate function
|
|
definition: <a name="(idx._(gentag._755))"></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_six.html#%28tech._puzzlestate%29" class="techoutside" data-pltdoc="x"><span class="techinside">PuzzleState</span></a><span class="RktCmt"> -> </span><a href="part_six.html#%28tech._puzzlestate%29" class="techoutside" data-pltdoc="x"><span class="techinside">PuzzleState</span></a></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">is the final state reachable from </span><span class="RktSym">state0</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span style="font-weight: bold">generative</span><span class="RktCmt"> creates a tree of possible boat rides </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">termination ???</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">solve</span><span class="hspace"> </span><span class="RktSym">initial-puzzle</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">final-puzzle</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">solve</span><span class="hspace"> </span><span class="RktSym">state0</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><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_six.html#%28tech._puzzlestate%29" class="techoutside" data-pltdoc="x"><span class="techinside">PuzzleState</span></a><span class="RktCmt">] -> </span><a href="part_six.html#%28tech._puzzlestate%29" class="techoutside" data-pltdoc="x"><span class="techinside">PuzzleState</span></a></td></tr><tr><td><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><span style="font-weight: bold">generative</span><span class="RktCmt"> generates the successors of </span><span class="RktSym">los</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">solve*</span><span class="hspace"> </span><span class="RktSym">los</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._ormap%29%29" class="RktValLink" data-pltdoc="x">ormap</a></span><span class="hspace"> </span><span class="RktSym">final?</span><span class="hspace"> </span><span class="RktSym">los</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="RktPn">(</span><span class="RktSym"><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><span class="hspace"> </span><span class="RktSym">final?</span><span class="hspace"> </span><span class="RktSym">los</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._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">solve*</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">create-next-states</span><span class="hspace"> </span><span class="RktSym">los</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><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">solve*</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">state0</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 auxiliary function uses generative recursion, generating all new
|
|
possibilities given a list of possibilities. If one of the given
|
|
possibilities is a final state, the function returns it.</div></p><p>Clearly, <span class="RktSym">solve</span> is quite generic. As long as you define a
|
|
collection of <a name="(tech._puzzlestate)"></a><span style="font-style: italic">PuzzleState</span>s, a function for recognizing final
|
|
states, and a function for creating all “successor” states,
|
|
<span class="RktSym">solve</span> can work on your puzzle.</p><p><a name="(counter._(exercise._ex~3amc-terminates))"></a><span style="font-weight: bold">Exercise</span> 520. The <span class="RktSym">solve*</span> function generates all
|
|
states reachable with <span style="font-style: italic">n</span> boat trips before it looks at states that
|
|
require <span style="font-style: italic">n + </span>1<span style="font-style: italic"></span> boat trips, even if some of those boat trips return
|
|
to previously encountered states. Because of this systematic way of
|
|
traversing the tree, <span class="RktSym">solve*</span> cannot go into an infinite loop. Why?
|
|
<span style="font-weight: bold">Terminology</span> This way of searching a tree or a graph is dubbed
|
|
<span style="font-style: italic">breadth-first search</span>. <a href="part_six.html#%28counter._%28exercise._ex~3amc-terminates%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._(exercise._ex~3amc-state))"></a><span style="font-weight: bold">Exercise</span> 521. Develop a representation for the states of
|
|
the missionary-and-cannibal puzzle. Like the graphical representation, a
|
|
data representation must record the number of missionaries and cannibals on
|
|
each side of the river plus the location of the boat.</p><p>The description of <a href="part_six.html#%28tech._puzzlestate%29" class="techoutside" data-pltdoc="x"><span class="techinside">PuzzleState</span></a> calls for a new structure
|
|
type. Represent the above initial, intermediate, and final states in your
|
|
representation.</p><p>Design the function <span class="RktSym">final?</span>, which detects whether in a given state
|
|
all people are on the right river bank.</p><p>Design the function <span class="RktSym">render-mc</span>, which maps a state of the
|
|
missionary-and-cannibal puzzle to an image. <a href="part_six.html#%28counter._%28exercise._ex~3amc-state%29%29" class="ex-end" data-pltdoc="x"></a></p><p>The problem is that returning the final state says nothing about how the
|
|
player can get from the initial state to the final one. In other words,
|
|
<span class="RktSym">create-next-states</span> forgets how it gets to the returned states
|
|
from the given ones. And this situation clearly calls for an accumulator,
|
|
but at the same time, the accumulated knowledge is best associated with
|
|
every individual <a href="part_six.html#%28tech._puzzlestate%29" class="techoutside" data-pltdoc="x"><span class="techinside">PuzzleState</span></a>, not <span class="RktSym">solve*</span> or any other
|
|
function.</p><p><a name="(counter._(exercise._ex~3amc-accu-state))"></a><span style="font-weight: bold">Exercise</span> 522. Modify the representation from
|
|
<a href="part_six.html#%28counter._%28exercise._ex~3amc-state%29%29" data-pltdoc="x">exercise 521</a> so that a state records the sequence of states
|
|
traversed to get there. Use a list of states.</p><p>Articulate and write down an accumulator statement with the data definition
|
|
that explains the additional field.</p><p>Modify <span class="RktSym">final?</span> or <span class="RktSym">render-mc</span> for this representation as needed. <a href="part_six.html#%28counter._%28exercise._ex~3amc-accu-state%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._(exercise._ex~3amc-next-state))"></a><span style="font-weight: bold">Exercise</span> 523. Design the <span class="RktSym">create-next-states</span>
|
|
function. It consumes lists of missionary-and-cannibal states and
|
|
generates the list of all those states that a boat ride can reach.</p><p>Ignore the accumulator in the first draft of <span class="RktSym">create-next-states</span>,
|
|
but make sure that the function does not generate states where the
|
|
cannibals can eat the missionaries.</p><p>For the second design, update the accumulator field in the state structures
|
|
and use it to rule out states that have been encountered on the way to the
|
|
current state. <a href="part_six.html#%28counter._%28exercise._ex~3amc-next-state%29%29" class="ex-end" data-pltdoc="x"></a></p><p><a name="(counter._(exercise._ex~3amc-solve))"></a><span style="font-weight: bold">Exercise</span> 524. Exploit the accumulator-oriented data
|
|
representation to modify <span class="RktSym">solve</span>. The revised function produces the
|
|
list of states that lead from the initial <a href="part_six.html#%28tech._puzzlestate%29" class="techoutside" data-pltdoc="x"><span class="techinside">PuzzleState</span></a> to the final one.</p><p>Also consider creating a movie from this list, using <span class="RktSym">render-mc</span> to
|
|
generate the images. Use <span class="RktSym"><a href="https://docs.racket-lang.org/teachpack/2htdpuniverse.html#%28def._%28%28lib._2htdp%2Funiverse..rkt%29._run-movie%29%29" class="RktValLink" data-pltdoc="x">run-movie</a></span> to display the movie. <a href="part_six.html#%28counter._%28exercise._ex~3amc-solve%29%29" class="ex-end" data-pltdoc="x"></a></p><h4>33.3<tt> </tt><a name="(part._sec~3afractal-acc)"></a>Accumulators as Results</h4><p><div class="SIntrapara">Take another look at <a href="part_five.html#%28counter._%28figure._fig~3asiepic%29%29" data-pltdoc="x">figure <span class="FigureRef">156</span></a>. It displays a Sierpinski triangle and a suggestion
|
|
how to create it. Specifically, the
|
|
images on the right explain one version of the generative idea behind the
|
|
process:
|
|
</div><div class="SIntrapara"><blockquote><p>The given problem is a triangle. When
|
|
the triangle is too small to be subdivided any further, the algorithm does
|
|
nothing; otherwise, it finds the midpoints of its three sides and deals
|
|
with the three outer triangles recursively.</p></blockquote></div><div class="SIntrapara">In contrast, <a href="part_five.html#%28part._sec~3afractal%29" data-pltdoc="x">Fractals, a First Taste</a> shows how to compose Sierpinski triangles
|
|
algebraically, a process that does not correspond to this description.</div></p><p><div class="SIntrapara">Most programmers expect “draw” to mean the action of adding a
|
|
triangle to some canvas. The <span class="RktSym"><a href="https://docs.racket-lang.org/teachpack/2htdpimage.html#%28def._%28%28lib._2htdp%2Fimage..rkt%29._scene%2Bline%29%29" class="RktValLink" data-pltdoc="x">scene+line</a></span> function from
|
|
<span class="sroman">the <span class="Smaller"><span style="font-style: italic">2htdp/image</span></span> teachpack</span> makes this idea concrete. The function consumes an image
|
|
<span class="RktSym">s</span> and the coordinates of two points and adds a line through these
|
|
two points to <span class="RktSym">s</span>. It is easy to generalize from <span class="RktSym"><a href="https://docs.racket-lang.org/teachpack/2htdpimage.html#%28def._%28%28lib._2htdp%2Fimage..rkt%29._scene%2Bline%29%29" class="RktValLink" data-pltdoc="x">scene+line</a></span>
|
|
to <span class="RktSym">add-triangle</span> and from there to <span class="RktSym">add-sierpinski</span>:
|
|
</div><div class="SIntrapara"><blockquote><p><span style="font-weight: bold">Sample Problem</span> Design the <span class="RktSym">add-sierpinski</span> function. It consumes an
|
|
image and three <a href="part_one.html#%28tech._posn%29" class="techoutside" data-pltdoc="x"><span class="techinside">Posn</span></a>s describing a triangle. It uses the latter to
|
|
add a Sierpinski triangle to this image.</p></blockquote></div><div class="SIntrapara">Note how this problem implicitly refers to the above process
|
|
description of how to draw a Sierpinski triangle. In other words, we are
|
|
confronted with a classical generative-recursive problem, and we can start
|
|
with the classic template of generative recursion and the four central
|
|
design questions:
|
|
</div><div class="SIntrapara"><ul><li><p>The problem is trivial if the triangle is too small to be
|
|
subdivided.</p></li><li><p>In the trivial case, the function returns the given image.</p></li><li><p>Otherwise the midpoints of the sides of the given triangle are
|
|
determined to add another triangle. Each “outer” triangle is then
|
|
processed recursively.</p></li><li><p>Each of these recursive steps produces an image. The remaining
|
|
question is how to combine these images.</p></li></ul></div></p><p><div class="SIntrapara"><a name="(idx._(gentag._756))"></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._image%29" class="techoutside" data-pltdoc="x"><span class="techinside">Image</span></a><span class="RktCmt"> </span><a href="part_one.html#%28tech._posn%29" class="techoutside" data-pltdoc="x"><span class="techinside">Posn</span></a><span class="RktCmt"> </span><a href="part_one.html#%28tech._posn%29" class="techoutside" data-pltdoc="x"><span class="techinside">Posn</span></a><span class="RktCmt"> </span><a href="part_one.html#%28tech._posn%29" class="techoutside" data-pltdoc="x"><span class="techinside">Posn</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 style="font-weight: bold">generative</span><span class="RktCmt"> adds the triangle (</span><span class="RktSym">a</span><span class="RktCmt">, </span><span class="RktSym">b</span><span class="RktCmt">, </span><span class="RktSym">c</span><span class="RktCmt">) to </span><span class="RktSym">scene0</span><span class="RktCmt">, </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">subdivides it into three triangles by taking the </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">midpoints of its sides; stop if (</span><span class="RktSym">a</span><span class="RktCmt">, </span><span class="RktSym">b</span><span class="RktCmt">, </span><span class="RktSym">c</span><span class="RktCmt">) is too small</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">add-sierpinski</span><span class="hspace"> </span><span class="RktSym">scene0</span><span class="hspace"> </span><span class="RktSym">a</span><span class="hspace"> </span><span class="RktSym">b</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#%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">too-small?</span><span class="hspace"> </span><span class="RktSym">a</span><span class="hspace"> </span><span class="RktSym">b</span><span class="hspace"> </span><span class="RktSym">c</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">scene0</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></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._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">scene1</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">add-triangle</span><span class="hspace"> </span><span class="RktSym">scene0</span><span class="hspace"> </span><span class="RktSym">a</span><span class="hspace"> </span><span class="RktSym">b</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"><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">mid-a-b</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">mid-point</span><span class="hspace"> </span><span class="RktSym">a</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">mid-b-c</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">mid-point</span><span class="hspace"> </span><span class="RktSym">b</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"><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">mid-c-a</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">mid-point</span><span class="hspace"> </span><span class="RktSym">c</span><span class="hspace"> </span><span class="RktSym">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#%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">scene2</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">add-sierpinski</span><span class="hspace"> </span><span class="RktSym">scene0</span><span class="hspace"> </span><span class="RktSym">a</span><span class="hspace"> </span><span class="RktSym">mid-a-b</span><span class="hspace"> </span><span class="RktSym">mid-c-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#%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">scene3</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">add-sierpinski</span><span class="hspace"> </span><span class="RktSym">scene0</span><span class="hspace"> </span><span class="RktSym">b</span><span class="hspace"> </span><span class="RktSym">mid-b-c</span><span class="hspace"> </span><span class="RktSym">mid-a-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">scene4</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">add-sierpinski</span><span class="hspace"> </span><span class="RktSym">scene0</span><span class="hspace"> </span><span class="RktSym">c</span><span class="hspace"> </span><span class="RktSym">mid-c-a</span><span class="hspace"> </span><span class="RktSym">mid-b-c</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><span class="RktCmt">—<wbr></wbr></span><span class="RktCmt">IN</span><span class="RktCmt">—<wbr></wbr></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">scene1</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">scene2</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">scene3</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><span class="RktPn">)</span></td></tr></table></blockquote></blockquote><p class="Centertext"><span class="Legend"><span class="FigureTarget"><a name="(counter._(figure._fig~3aaccu-result-gen-temp))" x-target-lift="Figure"></a>Figure 191: </span>Accumulators as results of generative recursions, a skeleton</span></p></blockquote></div></p><p><a href="part_six.html#%28counter._%28figure._fig~3aaccu-result-gen-temp%29%29" data-pltdoc="x">Figure <span class="FigureRef">191</span></a> shows the result of translating
|
|
these answers into a skeletal definition. Since each midpoint is used
|
|
twice, the skeleton 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 formulate the
|
|
generative step in ISL+. 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 introduces the
|
|
three new midpoints plus three recursive applications of
|
|
<span class="RktSym">add-sierpinski</span>. The dots in its body suggest a combination of the
|
|
scenes.</p><p><div class="SIntrapara"><a name="(counter._(exercise._ex~3asierpinski-aux))"></a><span style="font-weight: bold">Exercise</span> 525. Tackle the wish list that the
|
|
skeleton implies: <a name="(idx._(gentag._757))"></a> <a name="(idx._(gentag._758))"></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._image%29" class="techoutside" data-pltdoc="x"><span class="techinside">Image</span></a><span class="RktCmt"> </span><a href="part_one.html#%28tech._posn%29" class="techoutside" data-pltdoc="x"><span class="techinside">Posn</span></a><span class="RktCmt"> </span><a href="part_one.html#%28tech._posn%29" class="techoutside" data-pltdoc="x"><span class="techinside">Posn</span></a><span class="RktCmt"> </span><a href="part_one.html#%28tech._posn%29" class="techoutside" data-pltdoc="x"><span class="techinside">Posn</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">adds the black triangle </span><span class="RktSym">a</span><span class="RktCmt">, </span><span class="RktSym">b</span><span class="RktCmt">, </span><span class="RktSym">c</span><span class="RktCmt"> to </span><span class="RktSym">scene</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">add-triangle</span><span class="hspace"> </span><span class="RktSym">scene</span><span class="hspace"> </span><span class="RktSym">a</span><span class="hspace"> </span><span class="RktSym">b</span><span class="hspace"> </span><span class="RktSym">c</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">scene</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._posn%29" class="techoutside" data-pltdoc="x"><span class="techinside">Posn</span></a><span class="RktCmt"> </span><a href="part_one.html#%28tech._posn%29" class="techoutside" data-pltdoc="x"><span class="techinside">Posn</span></a><span class="RktCmt"> </span><a href="part_one.html#%28tech._posn%29" class="techoutside" data-pltdoc="x"><span class="techinside">Posn</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 the triangle </span><span class="RktSym">a</span><span class="RktCmt">, </span><span class="RktSym">b</span><span class="RktCmt">, </span><span class="RktSym">c</span><span class="RktCmt"> too small to be divided</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">too-small?</span><span class="hspace"> </span><span class="RktSym">a</span><span class="hspace"> </span><span class="RktSym">b</span><span class="hspace"> </span><span class="RktSym">c</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></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><a href="part_one.html#%28tech._posn%29" class="techoutside" data-pltdoc="x"><span class="techinside">Posn</span></a><span class="RktCmt"> </span><a href="part_one.html#%28tech._posn%29" class="techoutside" data-pltdoc="x"><span class="techinside">Posn</span></a><span class="RktCmt"> -> </span><a href="part_one.html#%28tech._posn%29" class="techoutside" data-pltdoc="x"><span class="techinside">Posn</span></a><span class="RktCmt"> </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">determines the midpoint between </span><span class="RktSym">a</span><span class="RktCmt"> and </span><span class="RktSym">b</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">mid-point</span><span class="hspace"> </span><span class="RktSym">a</span><span class="hspace"> </span><span class="RktSym">b</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktSym">a</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">Design the three functions. <a name="(idx._(gentag._759))"></a></div></p><p><div class="SIntrapara"><span style="font-weight: bold">Domain Knowledge</span> (1) For the <span class="RktSym">too-small?</span> function it suffices to
|
|
measure the distance between two points and to check whether it is below
|
|
some chosen threshold, say, <span class="RktVal">10</span>. The distance between
|
|
<span style="font-style: italic"></span>(<span style="font-style: italic">x</span><span style="vertical-align: sub; font-size: 80%"><span style="font-style: italic"></span>0<span style="font-style: italic"></span></span><span style="font-style: italic">,y</span><span style="vertical-align: sub; font-size: 80%"><span style="font-style: italic"></span>0<span style="font-style: italic"></span></span><span style="font-style: italic"></span>)<span style="font-style: italic"></span> and <span style="font-style: italic"></span>(<span style="font-style: italic">x</span><span style="vertical-align: sub; font-size: 80%"><span style="font-style: italic"></span>1<span style="font-style: italic"></span></span><span style="font-style: italic">,y</span><span style="vertical-align: sub; font-size: 80%"><span style="font-style: italic"></span>1<span style="font-style: italic"></span></span><span style="font-style: italic"></span>)<span style="font-style: italic"></span> is
|
|
</div><div class="SIntrapara"><blockquote class="SVInsetFlow"><blockquote class="SCentered"><p><img src="pict_298.png" alt="image" width="136" height="15"/></p></blockquote></blockquote></div><div class="SIntrapara">that is, the distance of <span style="font-style: italic"></span>(<span style="font-style: italic">x</span><span style="vertical-align: sub; font-size: 80%"><span style="font-style: italic"></span>0<span style="font-style: italic"></span></span><span style="font-style: italic"> - x</span><span style="vertical-align: sub; font-size: 80%"><span style="font-style: italic"></span>1<span style="font-style: italic"></span></span><span style="font-style: italic">,y</span><span style="vertical-align: sub; font-size: 80%"><span style="font-style: italic"></span>0<span style="font-style: italic"></span></span><span style="font-style: italic"> - y</span><span style="vertical-align: sub; font-size: 80%"><span style="font-style: italic"></span>1<span style="font-style: italic"></span></span><span style="font-style: italic"></span>)<span style="font-style: italic"></span> to the origin.</div></p><p><div class="SIntrapara">The midpoint between points <span style="font-style: italic"></span>(<span style="font-style: italic">x</span><span style="vertical-align: sub; font-size: 80%"><span style="font-style: italic"></span>0<span style="font-style: italic"></span></span><span style="font-style: italic">,y</span><span style="vertical-align: sub; font-size: 80%"><span style="font-style: italic"></span>0<span style="font-style: italic"></span></span><span style="font-style: italic"></span>)<span style="font-style: italic"></span> and <span style="font-style: italic"></span>(<span style="font-style: italic">x</span><span style="vertical-align: sub; font-size: 80%"><span style="font-style: italic"></span>1<span style="font-style: italic"></span></span><span style="font-style: italic">,y</span><span style="vertical-align: sub; font-size: 80%"><span style="font-style: italic"></span>1<span style="font-style: italic"></span></span><span style="font-style: italic"></span>)<span style="font-style: italic"></span> has as
|
|
coordinates the midpoints between the respective x and y coordinates:
|
|
</div><div class="SIntrapara"><blockquote class="SVInsetFlow"><blockquote class="SCentered"><p><img src="pict_299.png" alt="image" width="153" height="15"/>
|
|
<a href="part_six.html#%28counter._%28exercise._ex~3asierpinski-aux%29%29" class="ex-end" data-pltdoc="x"></a></p></blockquote></blockquote></div></p><p>Now that we have all the auxiliary functions, it is time to return to the problem
|
|
of combining the three images that are created by the recursive calls. One obvious
|
|
guess is to use the <span class="RktSym"><a href="https://docs.racket-lang.org/teachpack/2htdpimage.html#%28def._%28%28lib._2htdp%2Fimage..rkt%29._overlay%29%29" class="RktValLink" data-pltdoc="x">overlay</a></span> or <span class="RktSym"><a href="https://docs.racket-lang.org/teachpack/2htdpimage.html#%28def._%28%28lib._2htdp%2Fimage..rkt%29._underlay%29%29" class="RktValLink" data-pltdoc="x">underlay</a></span> function, but an evaluation
|
|
in the interactions area of DrRacket shows that the functions hide the underlying
|
|
triangles.</p><p><div class="SIntrapara">Specifically, imagine that the three recursive calls produce the following empty
|
|
scenes, enriched with a single triangle in appropriate locations:
|
|
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="stt">> </span><span class="RktSym">scene1</span></td></tr><tr><td><p><img style="vertical-align: 0px; margin: -3px -3px -3px -3px;" src="pict_300.png" alt="image" width="57" height="37"/></p></td></tr><tr><td><span class="stt">> </span><span class="RktSym">scene2</span></td></tr><tr><td><p><img style="vertical-align: 0px; margin: -3px -3px -3px -3px;" src="pict_301.png" alt="image" width="57" height="37"/></p></td></tr><tr><td><span class="stt">> </span><span class="RktSym">scene3</span></td></tr><tr><td><p><img style="vertical-align: 0px; margin: -3px -3px -3px -3px;" src="pict_302.png" alt="image" width="57" height="37"/></p></td></tr></table></blockquote></div><div class="SIntrapara">A combination should look like this figure:
|
|
</div><div class="SIntrapara"><blockquote><p><img style="vertical-align: 0px; margin: -3px -3px -3px -3px;" src="pict_303.png" alt="image" width="56" height="36"/></p></blockquote></div><div class="SIntrapara">But, combining these shapes with <span class="RktSym"><a href="https://docs.racket-lang.org/teachpack/2htdpimage.html#%28def._%28%28lib._2htdp%2Fimage..rkt%29._overlay%29%29" class="RktValLink" data-pltdoc="x">overlay</a></span> or <span class="RktSym"><a href="https://docs.racket-lang.org/teachpack/2htdpimage.html#%28def._%28%28lib._2htdp%2Fimage..rkt%29._underlay%29%29" class="RktValLink" data-pltdoc="x">underlay</a></span>
|
|
does not yield this desired shape:
|
|
</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/teachpack/2htdpimage.html#%28def._%28%28lib._2htdp%2Fimage..rkt%29._overlay%29%29" class="RktValLink" data-pltdoc="x">overlay</a></span><span class="hspace"> </span><span class="RktSym">scene1</span><span class="hspace"> </span><span class="RktSym">scene2</span><span class="hspace"> </span><span class="RktSym">scene3</span><span class="RktPn">)</span></td></tr><tr><td><p><img style="vertical-align: 0px; margin: -3px -3px -3px -3px;" src="pict_304.png" alt="image" width="57" height="37"/></p></td></tr><tr><td><span class="stt">> </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._underlay%29%29" class="RktValLink" data-pltdoc="x">underlay</a></span><span class="hspace"> </span><span class="RktSym">scene1</span><span class="hspace"> </span><span class="RktSym">scene2</span><span class="hspace"> </span><span class="RktSym">scene3</span><span class="RktPn">)</span></td></tr><tr><td><p><img style="vertical-align: 0px; margin: -3px -3px -3px -3px;" src="pict_305.png" alt="image" width="57" height="37"/></p></td></tr></table></blockquote></div><div class="SIntrapara">Indeed, the image teachpack of ISL+ does not support a function that
|
|
combines these scenes in an appropriate manner.</div></p><p><div class="SIntrapara">Let’s take a second look at these interactions. If <span class="RktSym">scene1</span> is the
|
|
result of adding the upper triangle to the given scene and <span class="RktSym">scene2</span>
|
|
is the result of adding a triangle on the lower left, perhaps the second
|
|
recursive call should add triangles to the result of the first call. Doing
|
|
so would yield
|
|
</div><div class="SIntrapara"><blockquote><p><img style="vertical-align: 0px; margin: -3px -3px -3px -3px;" src="pict_306.png" alt="image" width="56" height="36"/></p></blockquote></div><div class="SIntrapara">and handing over this scene to the third recursive call produces exactly
|
|
what is wanted:
|
|
</div><div class="SIntrapara"><blockquote><p><img style="vertical-align: 0px; margin: -3px -3px -3px -3px;" src="pict_307.png" alt="image" width="56" height="36"/></p></blockquote></div></p><p><div class="SIntrapara"><a name="(idx._(gentag._760))"></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._image%29" class="techoutside" data-pltdoc="x"><span class="techinside">Image</span></a><span class="RktCmt"> </span><a href="part_one.html#%28tech._posn%29" class="techoutside" data-pltdoc="x"><span class="techinside">Posn</span></a><span class="RktCmt"> </span><a href="part_one.html#%28tech._posn%29" class="techoutside" data-pltdoc="x"><span class="techinside">Posn</span></a><span class="RktCmt"> </span><a href="part_one.html#%28tech._posn%29" class="techoutside" data-pltdoc="x"><span class="techinside">Posn</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 style="font-weight: bold">generative</span><span class="RktCmt"> adds the triangle (</span><span class="RktSym">a</span><span class="RktCmt">, </span><span class="RktSym">b</span><span class="RktCmt">, </span><span class="RktSym">c</span><span class="RktCmt">) to </span><span class="RktSym">scene0</span><span class="RktCmt">, </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">subdivides it into three triangles by taking the </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">midpoints of its sides; stop if (</span><span class="RktSym">a</span><span class="RktCmt">, </span><span class="RktSym">b</span><span class="RktCmt">, </span><span class="RktSym">c</span><span class="RktCmt">) is too small</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span style="font-weight: bold">accumulator</span><span class="RktCmt"> the function accumulates the triangles of </span><span class="RktSym">scene0</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">add-sierpinski</span><span class="hspace"> </span><span class="RktSym">scene0</span><span class="hspace"> </span><span class="RktSym">a</span><span class="hspace"> </span><span class="RktSym">b</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#%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">too-small?</span><span class="hspace"> </span><span class="RktSym">a</span><span class="hspace"> </span><span class="RktSym">b</span><span class="hspace"> </span><span class="RktSym">c</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktSym">scene0</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></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._define%29%29" class="RktStxLink" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">scene1</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">add-triangle</span><span class="hspace"> </span><span class="RktSym">scene0</span><span class="hspace"> </span><span class="RktSym">a</span><span class="hspace"> </span><span class="RktSym">b</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"><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">mid-a-b</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">mid-point</span><span class="hspace"> </span><span class="RktSym">a</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">mid-b-c</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">mid-point</span><span class="hspace"> </span><span class="RktSym">b</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"><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">mid-c-a</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">mid-point</span><span class="hspace"> </span><span class="RktSym">c</span><span class="hspace"> </span><span class="RktSym">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#%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">scene2</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">add-sierpinski</span><span class="hspace"> </span><span class="highlighted"><span class="RktSym">scene1</span></span><span class="hspace"> </span><span class="RktSym">a</span><span class="hspace"> </span><span class="RktSym">mid-a-b</span><span class="hspace"> </span><span class="RktSym">mid-c-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#%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">scene3</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">add-sierpinski</span><span class="hspace"> </span><span class="highlighted"><span class="RktSym">scene2</span></span><span class="hspace"> </span><span class="RktSym">b</span><span class="hspace"> </span><span class="RktSym">mid-b-c</span><span class="hspace"> </span><span class="RktSym">mid-a-b</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><span class="RktCmt">—<wbr></wbr></span><span class="RktCmt">IN</span><span class="RktCmt">—<wbr></wbr></span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">add-sierpinski</span><span class="hspace"> </span><span class="highlighted"><span class="RktSym">scene3</span></span><span class="hspace"> </span><span class="RktSym">c</span><span class="hspace"> </span><span class="RktSym">mid-c-a</span><span class="hspace"> </span><span class="RktSym">mid-b-c</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></blockquote><p class="Centertext"><span class="Legend"><span class="FigureTarget"><a name="(counter._(figure._fig~3aadd-sierpinski))" x-target-lift="Figure"></a>Figure 192: </span>Accumulators as results of generative recursion, the function</span></p></blockquote></div></p><p><a href="part_six.html#%28counter._%28figure._fig~3aadd-sierpinski%29%29" data-pltdoc="x">Figure <span class="FigureRef">192</span></a> shows the reformulation based on this insight.
|
|
The three highlights pinpoint the key design idea. All concern the case
|
|
when the triangle is sufficiently large and it is added to the given scene.
|
|
Once its sides are subdivided, the first outer triangle is recursively
|
|
processed using <span class="RktSym">scene1</span>, the result of adding the given
|
|
triangle. Similarly, the result of this first recursion, dubbed
|
|
<span class="RktSym">scene2</span>, is used for the second recursion, which is about
|
|
processing the second triangle. Finally, <span class="RktSym">scene3</span> flows into the
|
|
third recursive call. In sum, the novelty is that the accumulator is
|
|
simultaneously an argument, a tool for collecting knowledge, and the
|
|
result of the function.</p><p><div class="SIntrapara">To explore <span class="RktSym">add-sierpinski</span> it is best to start from an equilateral
|
|
triangle and an image that leaves a sufficiently large border. Here are
|
|
definitions that meet these two criteria:
|
|
</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">MT</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._empty-scene%29%29" class="RktValLink" data-pltdoc="x">empty-scene</a></span><span class="hspace"> </span><span class="RktVal">400</span><span class="hspace"> </span><span class="RktVal">400</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">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._make-posn%29%29" class="RktValLink" data-pltdoc="x">make-posn</a></span><span class="hspace"> </span><span class="RktVal">200</span><span class="hspace"> </span><span class="RktVal">50</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">B</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._make-posn%29%29" class="RktValLink" data-pltdoc="x">make-posn</a></span><span class="hspace"> </span><span class="RktVal">27</span><span class="hspace"> </span><span class="RktVal">350</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">C</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._make-posn%29%29" class="RktValLink" data-pltdoc="x">make-posn</a></span><span class="hspace"> </span><span class="RktVal">373</span><span class="hspace"> </span><span class="RktVal">350</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">add-sierpinski</span><span class="hspace"> </span><span class="RktSym">MT</span><span class="hspace"> </span><span class="RktSym">A</span><span class="hspace"> </span><span class="RktSym">B</span><span class="hspace"> </span><span class="RktSym">C</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara">Check what kind of Sierpinski fractal this code fragment
|
|
delivers. Experiment with the definitions from <a href="part_six.html#%28counter._%28exercise._ex~3asierpinski-aux%29%29" data-pltdoc="x">exercise 525</a> to
|
|
create sparser and denser Sierpinski triangles than the first one.</div></p><p><a name="(counter._(exercise._ex~3asierpinski-start))"></a><span style="font-weight: bold">Exercise</span> 526. To compute the endpoints of an equilateral
|
|
Sierpinski triangle, draw a circle and pick three points on the circle that
|
|
are 120 degrees apart, for example, 120, 240, and 360.</p><p><div class="SIntrapara">Design the function <span class="RktSym">circle-pt</span>: <a name="(idx._(gentag._761))"></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">CENTER</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._make-posn%29%29" class="RktValLink" data-pltdoc="x">make-posn</a></span><span class="hspace"> </span><span class="RktVal">200</span><span class="hspace"> </span><span class="RktVal">200</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">RADIUS</span><span class="hspace"> </span><span class="RktVal">200</span><span class="RktPn">)</span><span class="hspace"> </span><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">the radius in pixels </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._number%29" class="techoutside" data-pltdoc="x"><span class="techinside">Number</span></a><span class="RktCmt"> -> </span><a href="part_one.html#%28tech._posn%29" class="techoutside" data-pltdoc="x"><span class="techinside">Posn</span></a></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">determines the point on the circle with </span><span class="RktSym">CENTER</span><span class="RktCmt"> </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">and </span><span class="RktSym">RADIUS</span><span class="RktCmt"> whose angle is </span></td></tr><tr><td><span class="hspace"> </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span style="font-weight: bold">examples</span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">what are the x and y coordinates of the desired </span></td></tr><tr><td><span class="RktCmt">;</span><span class="RktCmt"> </span><span class="RktCmt">point, when given: 120/360, 240/360, 360/360</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">circle-pt</span><span class="hspace"> </span><span class="RktSym">factor</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._make-posn%29%29" class="RktValLink" data-pltdoc="x">make-posn</a></span><span class="hspace"> </span><span class="RktVal">0</span><span class="hspace"> </span><span class="RktVal">0</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote></div><div class="SIntrapara"><span style="font-weight: bold">Domain Knowledge</span> This design problem calls on knowledge from
|
|
mathematics. One way to view the problem is as a conversion of a complex
|
|
number from the polar-coordinate representation to the <a href="part_one.html#%28tech._posn%29" class="techoutside" data-pltdoc="x"><span class="techinside">Posn</span></a>
|
|
representation. 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._make-polar%29%29" class="RktValLink" data-pltdoc="x">make-polar</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._real-part%29%29" class="RktValLink" data-pltdoc="x">real-part</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._imag-part%29%29" class="RktValLink" data-pltdoc="x">imag-part</a></span> in ISL+. Another way is to use trigonometry,
|
|
<span class="RktSym"><a href="https://docs.racket-lang.org/htdp-langs/intermediate-lam.html#%28def._htdp-intermediate-lambda._%28%28lib._lang%2Fhtdp-intermediate-lambda..rkt%29._sin%29%29" class="RktValLink" data-pltdoc="x">sin</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._cos%29%29" class="RktValLink" data-pltdoc="x">cos</a></span>, to determine the coordinates. If you
|
|
choose this route, recall that these trigonometry functions
|
|
compute the sine and cosine in terms of radians, not degrees. Also keep
|
|
in mind that on-screen positions grow downward, not upward. <a href="part_six.html#%28counter._%28exercise._ex~3asierpinski-start%29%29" class="ex-end" data-pltdoc="x"></a></div></p><p><div class="SIntrapara"><a name="(counter._(exercise._ex~3atree-generation))"></a><span style="font-weight: bold">Exercise</span> 527. Take a look at the following two images:
|
|
</div><div class="SIntrapara"><blockquote class="SCentered"><p><img style="vertical-align: 0px; margin: -3px -3px -3px -3px;" src="pict_308.png" alt="image" width="138.0" height="138.0"/><span class="hspace"> </span><img style="vertical-align: 0px; margin: -3px -3px -3px -3px;" src="pict_309.png" alt="image" width="138.0" height="138.0"/></p></blockquote></div><div class="SIntrapara">They demonstrate how to generate a fractal Savannah tree in the same way that
|
|
<a href="part_five.html#%28counter._%28figure._fig~3asiepic%29%29" data-pltdoc="x">figure <span class="FigureRef">156</span></a> shows how to draw a Sierpinski triangle. The
|
|
image on the left shows what a fractal Savannah tree looks like. The right
|
|
one explains the generative construction step.</div></p><p>Design the function <span class="RktSym">add-savannah</span>. The function consumes an image
|
|
and four numbers: (1) the x-coordinate of a line’s base point, (2)
|
|
the y-coordinate of a line’s base point, (3) the length of the line,
|
|
and (4) the angle of the line. It adds a fractal Savannah tree to the given
|
|
image.</p><p>Unless the line is too short, the function adds the specified line to the
|
|
image. It then divides the line into three segments. It recursively uses
|
|
the two intermediate points as the new starting points for two lines. The
|
|
lengths and the angles of the two branches change in a fixed manner, but
|
|
independently of each other. Use constants to define these changes and work
|
|
with them until you like your tree well enough.</p><p><span style="font-weight: bold">Hint</span> Experiment with shortening each left branch by at least one
|
|
third and rotating it left by at least <span class="RktVal">0.15</span> degrees. For each right
|
|
branch, shorten it by at least 20% and rotate it by <span class="RktVal">0.2</span> degrees in
|
|
the opposite direction. <a href="part_six.html#%28counter._%28exercise._ex~3atree-generation%29%29" class="ex-end" data-pltdoc="x"></a></p><p><div class="SIntrapara"><a name="(counter._(exercise._ex~3abezier))"></a><span style="font-weight: bold">Exercise</span> 528. Graphics programmers often need to connect two
|
|
points with a smooth curve where “smooth” is relative to some
|
|
perspective.<span class="refelem"><span class="refcolumn"><span class="refcontent">Géraldine Morin suggested this exercise.</span></span></span>
|
|
Here are two sketches:
|
|
</div><div class="SIntrapara"><blockquote class="SCentered"><p><img style="vertical-align: 0px; margin: -3px -3px -3px -3px;" src="pict_310.png" alt="image" width="138.0" height="138.0"/><span class="hspace"> </span><img style="vertical-align: 0px; margin: -3px -3px -3px -3px;" src="pict_311.png" alt="image" width="138.0" height="138.0"/></p></blockquote></div><div class="SIntrapara">The left one shows a smooth curve, connecting points <span style="font-style: italic">A</span> and
|
|
<span style="font-style: italic">C</span>; the right one supplies the perspective point, <span style="font-style: italic">B</span>, and the
|
|
angle of an observer.</div></p><p><div class="SIntrapara">One method for drawing such curves is due to Bézier. It is a prime example
|
|
of generative recursion, and the following sequence explains the
|
|
<span style="font-style: italic">eureka!</span> behind the algorithm:
|
|
</div><div class="SIntrapara"><blockquote class="SCentered"><p><img style="vertical-align: 0px; margin: -3px -3px -3px -3px;" src="pict_312.png" alt="image" width="138.0" height="138.0"/><span class="hspace"> </span><img style="vertical-align: 0px; margin: -3px -3px -3px -3px;" src="pict_313.png" alt="image" width="138.0" height="138.0"/><span class="hspace"> </span><img style="vertical-align: 0px; margin: -3px -3px -3px -3px;" src="pict_314.png" alt="image" width="138.0" height="138.0"/></p></blockquote></div><div class="SIntrapara">Consider the image on the left. It reminds you that the three given points determine a
|
|
triangle and that the connection from <span style="font-style: italic">A</span> to <span style="font-style: italic">C</span> is the focal
|
|
point of the algorithm. The goal is to pull the line from <span style="font-style: italic">A</span> to
|
|
<span style="font-style: italic">C</span> toward <span style="font-style: italic">B</span> so that it turns into a smooth curve.</div></p><p>Now turn to the image in the middle. It explains the essential idea of the
|
|
generative step. The algorithm determines the midpoint on the two observer
|
|
lines, <span style="font-style: italic">A-B</span> and <span style="font-style: italic">B-C</span>, as well as their midpoint, <span style="font-style: italic">A-B-C</span>.</p><p>Finally, the right-most image shows how these three new points generate
|
|
two distinct recursive calls: one deals with the new triangle on the left
|
|
and the other one with the triangle on the right. More precisely,
|
|
<span style="font-style: italic">A-B</span> and <span style="font-style: italic">B-C</span> become the new observer points and the lines
|
|
from <span style="font-style: italic">A</span> to <span style="font-style: italic">A-B-C</span> and from <span style="font-style: italic">C</span> to <span style="font-style: italic">A-B-C</span> become the
|
|
foci of the two recursive calls.</p><p>When the triangle is small enough, we have a trivially solvable case. The
|
|
algorithm just draws the triangle, and it appears as a point on the given
|
|
image. As you implement this algorithm, you need to experiment with
|
|
the notion of “small enough” to make the curve look smooth. <a href="part_six.html#%28counter._%28exercise._ex~3abezier%29%29" class="ex-end" data-pltdoc="x"></a></p><h3>34<tt> </tt><a name="(part._ch~3asummary6)"></a>Summary</h3><p><div class="SIntrapara">This last part is about designing with accumulators, a mechanism for
|
|
collecting knowledge during a data structure traversal. Adding an
|
|
accumulator can fix performance flaws and eliminate <a name="(idx._(gentag._762))"></a>termination problems.
|
|
Your takeaway from this part are two and a half design lessons:
|
|
</div><div class="SIntrapara"><ol><li><p>The first step is to recognize the need for introducing an
|
|
accumulator. Traversals “forget” pieces of the argument when
|
|
they step from one piece to the next. If you discover that such knowledge could simplify the
|
|
function’s design, consider introducing an accumulator. The first step is
|
|
to switch to the <span style="font-weight: bold">accumulator template</span>.</p></li><li><p>The key step is to formulate an <a name="(idx._(gentag._763))"></a>accumulator statement. The latter
|
|
must express <span style="font-weight: bold">what knowledge</span> the accumulator gathers <span style="font-weight: bold">as what
|
|
kind of data</span>. In most cases, the accumulator statement describes the
|
|
difference between the original argument and the current one.</p></li><li><p>The third step, a minor one, is to deduce from the accumulator
|
|
statement (a) what the initial accumulator value is, (b) how to maintain it
|
|
during traversal steps, and (c) how to exploit its knowledge.</p></li></ol></div></p><p>The idea of accumulating knowledge is ubiquitous, and it appears in many
|
|
different forms and shapes. It is widely used in so-called functional
|
|
languages like ISL+. Programmers using imperative languages encounter
|
|
accumulators in a different way, mostly via assignment statements in primitive
|
|
looping constructs because the latter cannot return values. Designing such
|
|
imperative accumulator programs proceeds just like the design of accumulator
|
|
functions here, but the details are beyond the scope of this first book on
|
|
systematic program design.</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="i5-6.html" title="backward to "Intermezzo 5: The Cost of Computation"" 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="part_epilogue.html" title="forward to "Epilogue: Moving On"" data-pltdoc="x">next →</a></span> </div></div></div><div id="contextindicator"> </div></body></html> |