<?php require_once "fs_inner_context.inc"; ?>
<!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=US-ASCII">

<title><?php echo $HTML_TITLE; ?></title>

</head>

<?php echo html_bgcolor_body($BG_COLOR); ?>

<!-- Standard hierarchical header structure -->

<?php echo $CS_HEADER_HTML; ?>

<?php echo html_linked_text("<em>Courses</em>", $CS_COURSES_ROOT_URL); ?>

<?php echo $HTML_HEADER; ?>

<hr><hr>

<p>Assignment #4 is due at 11:59 PM on Wednesday 29 October, 2003.</p>

<p>This assignment is an exercise in the definition and use of
data abstraction.</p>

<p>Section 2.1.2 of S&amp;IoCP discusses <em>data abstraction</em> and
its key component, the <em>abstraction barrier</em>. Data abstraction,
does <em>not</em> provide any new power for computing particular
functions. But it provides a crucial organizational principle, without
which moderate to large pieces of software can fall into chaos. The
basic idea of data abstraction is to divide the conceptual portions of
a piece of software into independent domains, separated by
abstraction barriers, so that we may work on any one of the domains
without knowing the internal details of the others. This allows a team
to divide the work on a large project among the different team
members. It also allows an individual programmer to concentrate on one
portion of a project at a time. For practical purposes, when dealing
with complex piles of information such as programs, a single person on
subsequent days of the week is a lot like a bunch of different
people.</p>

<p><?php echo html_linked_text("Last year's assignment #4",
                               "http://www.classes.cs.uchicago.edu/classes/archive/2002/fall/12500-1/Homework/Asst4/") . " "; ?>

exercised abstraction barriers in a slightly more sophisticated
fashion than this year's assignment.</p>

<?php echo html_header($HTML_HEADER_LEVEL + 1,
                       "0. Organization of the PAC"); ?>

<p>Look at the slightly censored code of my

<?php echo html_linked_text("pretty bad prototype of the Perfectly
                             Accurate Calculator",
           "../Project/GUI/perfectly_accurate_calculator-1,mod1.2-.scm"); ?>.

Make sure you are looking at the new version 1,mod1.2. I changed quite
a bit from the version 1,mod1.1 that I posted with Assignment #3. As
well as censoring some portions that I want you to figure out, I
commented out some of my partial code, and replaced it with trivial
function definitions to get off the ground.</p>

<p>Don't try to understand all of the code. But notice that the code has
two key sections: <em>Model</em>, and <em>View</em>, with an
abstraction barrier between them. The barrier is given by the list of
functions starting with <code>M-</code>, and the list of functions
starting with <code>V-</code>:</p>

<dl>

<dt>Model functions</dt>

<dd>

<dl>

<dt>Formula datatype</dt>

<dd>

<dl>

<dt>Operators</dt>

<dd><code>'+</code>, <code>'-</code>, <code>'*</code>,
<code>'/</code>, <code>'expt</code>, <code>'fib</code></dd>

<dt>Formula constructors</dt>

<dd>

<ul>

<li><code>M-empty_formula</code></li>

<li><code>M-number-&gt;formula</code></li>

<li><code>M-apply_operator_to_formulas</code></li>

</ul>

</dd>

<dt>Formula tests and selectors</dt>

<dd>

<ul>

<li><code>M-number_formula?</code></li>

<li><code>M-formula_number</code></li>

<li><code>M-formula_operator</code></li>

<li><code>M-formula_argument_list</code></li>

</ul>

</dd>

<dt>Other Formula operations</dt>

<dd>

<ul>

<li><code>M-evaluate_formula</code></li>

</ul>

</dd>

</dl>

</dd>

<dt>Value datatype</dt>

<dd>

<dl>

<dt>Value constructor</dt>

<dd>

<ul>

<li><code>M-number-&gt;value</code></li>

</ul>

</dd>

<dt>Value tests and selectors</dt>

<dd>

<ul>

<li><code>M-number_value?</code></li>

<li><code>M-value_number</code></li>

</ul>

</dd>

</dl>

</dd>

<dt>Model state</dt>

<dd>

<ul>

<li><code>M-set_input_formula</code></li>

<li><code>M-input_formula</code></li>

<li><code>M-set_output_formula</code></li>

<li><code>M-output_formula</code></li>

</ul>

</dd>

</dl>

</dd>

<dt>View Functions</dt>

<dd>

<ul>

<li><code>V-display_input_formula</code></li>

<li><code>V-display_output_formula</code></li>

</ul>

</dd>

</dl>

<p>The <em>Model</em> component of the PAC is responsible for all of
the manipulations of the basic concepts that the PAC works
with---numerical values, numerical formulae, and states of operation
with those. The <em>View</em> component is responsible for all of the
interaction with a user. Definitions outside of the <em>Model</em>
component (particularly, those in the <em>View</em> component) may
only interact with a formula or model state through those functions
from the <em>Model</em> component beginning with
<code>M-</code>. Similarly, definitions outside of the <em>View</em>
component may interact with the user interface through those functions
from the <em>View</em> component beginning with <code>V-</code>. These
rules establish a sort of <em>abstraction barrier</em> between the
definitions inside each main component, and the rest of the PAC
definitions.</p>

<p>Data abstraction is one of the key ideas in object-oriented
programming. Some programming languages have specific constructs to
indicate and enforce abstraction barriers. Abstraction barriers in
<em>Scheme</em> are essentially voluntary. There are extra
<em>Scheme</em> libraries that allow us to define and enforce
abstraction barriers, but we will stick to the voluntary approach for
now.</p>

<p>Within the <em>Model</em> component, there are subdivisions into
the <em>formula datatype</em>, the <em>value datatype</em>, and the
<em>Model state</em>. The formula and value datatypes have no need to
use functions defined in the <em>Model</em> state subcomponent. The
<em>Model</em> state subcomponent may only use the listed interface
functions from the formula and value datatypes. It seemed excessive to
add another mark for those functions, but the abstraction barriers
around the two subcomponents are also important to keep the PAC code
well organized.</p>

<p>The value datatype is so trivial that it's a bit annoying. But it
will become much more sophisticated in a few weeks when we implement
exact real values. By carrying along the abstraction barrier for the
trivial value datatype, we'll be ready to plug in more sophisticated
implementations of values as we cook them up.</p>

<p>I find that the proliferation of names in code like this makes it
impossible to be either perfectly systematic, or enjoyably readable,
much less both. I try to pick a middle course that's not too horrific,
and to mostly go toward systematic. So I marked all the interface
functions for the two major components, Model and View with
<code>M-</code> and <code>V-</code>, respectively. But I didn't mark
the interface components for the datatypes within the model. In the
abstract datatypes, I gave constructors and other operations names
<em>beginning</em> with the name of the datatype, I gave tests names
<em>ending</em> in a question mark, and I gave selectors names
<em>ending</em> in the name of the datatype. That's one of several
conventions for naming functions in an abstract datatype. None of them
seems to be really enjoyable. This one makes your eyes fuzz over
distinguishing <code>number->formula</code> from
<code>formula_number</code>, but we'll just squint and bear it.</p>

<p>Every abstraction barrier is an organizational aid, but also a
constraint on further development of software (the two qualities are
inextricably connected). As long as further development fits the
constraints imposed by our abstraction barriers, the barriers simplify
our thinking and help avoid lots of mistakes. Occasionally, we must
change the barriers. That is a much more costly step than working
within a single component. It may require changes to all software
components that use the functions in the barrier that we change.</p>

<p>The key to testing an abstract datatype is to test the correct
relationship between constructors and selectors and the other
functions if any. You may look directly at the list representations to
get an idea what's up. But as the datatypes become more sophisticated,
that may be difficult or impossible, and you need test suites based on
the relationships between functions.</p>

<p>Run the PAC, and just notice what the buttons do.</p>

<ol>

<li>Type a concrete syntax of an expression in the top
window.<br><br></li>

<li>Push the "Display Input" button to parse the concrete syntax into
an abstract syntax, and display that abstract syntax in the middle
window.<br><br></li>

<li>Push the "Evaluate" button to evaluate the abstract syntax, and
display the result in the bottom window.<br><br></li>

</ol>

<p>A final product probably won't have a button to incorporate the
input. That will more likely be done automatically on entry. Probably
either the concrete syntax as entered by the user will be the only
input display, or the display of abstract syntax will be substantially
different, perhaps a graphical display instead of textual. The current
layout makes it easier to observe what's going on. The current version
shows the abstract syntax in a more compact form that you see in the
<em>DrScheme</em> interaction window or test suite window. Instead of
<code>(list '+ 2 3)</code> you just see <code>(+ 2 3)</code>.</p>


<?php echo html_header($HTML_HEADER_LEVEL + 1,
                       "1. Incorporate your parser in the PAC code"); ?>

<p><strong>From now on, you should routinely save every meaningful
intermediate step in your work. I will stop mentioning that after one
more time.</strong></p>

<p>Replace my incredibly stupid parser, which just assumes that the
only possible operation is addition, with your much better recursive
descent parser. If you did sufficient testing in Assignment #3,
there's not much point in running a test suite for this step. Observe
the behavior of the PAC GUI with your new parser, as a sanity check
that you put your parser in correctly. But the GUI is not good for
much serious testing. Most serious testing works much better with
direct calls to the defined functions. Since you haven't changed
those, there's nothing in particular to test.</p>

<p>Some of the structure of the solution is already there, in
commented sections. You can remove the comment marks, and then
substitute in your code, or just use the commented parts as
guideposts.</p>

<p>With your improved parser, the PAC GUI can evaluate any formula
with addition, subtraction, multiplication, division, and
exponentiation. But it can't deal with the Fibonacci function. That's
not the fault of your parser. It's the fault of the evaluator, which
has no interpretation of <code>'fib</code>. This sort of skew between
components is part of the reason that you should test through internal
function calls, rather than through the GUI.</p>

<?php echo html_header($HTML_HEADER_LEVEL + 1,
                       "2. Adjust your parser to the abstraction barrier"); ?>

<p>Your work in step 1 violates the abstraction barrier around the
formula datatype. When you construct an abstract syntax in the form
<code>(list &lt;operator&gt; &lt;operand&gt; &lt;operand&gt;)</code>
you use internal knowledge of the representation of a formula, which
will change in later steps.</p>

<p>Fix your parser code to respect the abstraction barrier, by having
it use the functions <code>M-apply_operator_to_formulas</code>, etc.,
instead of <code>list</code>. Rerun your test suite from Assignment #3
on the new code. It should produce exactly the same results. You
should catch any little typos you made replacing the direct
construction of lists with the abstract formula constructors.</p>

<p>Even though this step is conceptually trivial, I did it one
<code>parse_&lt;nt&gt;</code> function at a time, testing in
between.</p>

<?php echo html_header($HTML_HEADER_LEVEL + 1,
                       "3. Try a variant representation of a formula"); ?>

<p><strong>Make sure that you saved your work from step 2. We will
back out of step 3, and pick up the step 2 version in step
4.</strong></p>

<p>As a quick exercise to demonstrate the independence of code within
the formula datatype and code outside, we'll try an easy variation on
the formula datatype. Instead of representing the application of a
binary operator to its arguments in the form</p>

<blockquote><pre><code>
(list &lt;operator&gt; &lt;operand1&gt; &lt;operand2&gt;)
</code></pre></blockquote>

<p>use the alternate form</p>

<blockquote><pre><code>
(cons (cons &lt;operator&gt; &lt;operand1&gt;) &lt;operand2&gt;)
</code></pre></blockquote>

<p>Similarly, the three-argument operator <code>fib</code> applies in
the form:</p>

<blockquote><pre><code>
(cons (cons (cons &lt;operator&gt; &lt;operand1&gt;) &lt;operand2&gt;) &lt;operand3&gt;)
</code></pre></blockquote>

<p>These forms are not well-formed <em>Scheme</em> lists, but they use
the bottom level implementation a tiny bit more efficiently. They
actually resemble the structure of the notation for function
application in <em>ML</em> and <em>Haskell</em>.</p>

<p>Some of the constructors and selectors become recursive in this
representation.</p>

<p>You should be able to switch back and forth between the two
representations of the formula datatype with no observable change in
the behavior of the GUI. If you have the energy, you can try the
switch again with your evaluator in play.</p>

<?php echo html_header($HTML_HEADER_LEVEL + 1,
                       "4. Write your own evaluator"); ?>

<p>Back up to your version from step 2, which you saved. Replace my
definition of <code>M-evaluate_formula</code> with your own recursive
definition of the evaluation of a formula (in abstract syntax form)
involving, addition, multiplication, subtraction, division,
exponentiation, and the Fibonacci function. Use your best code for
<code>fib</code> from Assignment #1.</p>

<p>My old definition of <code>M-evaluate_formula</code> is tiny, but
it's still a tiny bit interesting. <code>(eval fmla_to_eval)</code>
actually calls <em>Scheme</em>'s very own evaluator, the same one that
is evaluating all of our work, including the PAC GUI as a whole.</p>

<p>The availability of the whole programming language within one of
its own function calls is a very interesting property of
<em>Scheme</em>. Back in the old days, a lot of people found this
notion of a program invoking the interpreter for its own programming
language almost mystical. They called the <em>LISP</em> and
<em>Scheme</em> implementations <em>metacircular interpreters</em>. I
think that's a tad pretentious, but the feature is rather nice in a
number of ways, both practical and conceptual.</p>

<p>The real reason that self-invocation is hard, and not usually
available in other programming languages, has more to do with their
complicated syntax than it does with the sophistication of their
evaluation mechanisms. It's mainly the very simple syntax of
<em>LISP</em>/<em>Scheme</em> that makes it relatively easy to
incorporate the <code>eval</code> function.</p>

<p>The availability of <code>eval</code> let me create a prototype
calculator with a fairly powerful evaluator in a few keystrokes. It's
a very big help at the beginning of a project to have a lot of the
work already done for you. So why are we replacing my
<code>M-evaluate_formula</code> based on <em>Scheme</em>'s
<code>eval</code>? The only extra power that we are adding is the
power to evaluate applications of the Fibonacci function. Although
<code>fib</code> isn't predefined in <em>Scheme</em>, I'm sure I could
have found a way to invoke <em>Scheme</em>'s <code>eval</code> with
some additional definitions. There are two remaining reasons to
replace the easy (because somebody else did the work)
<code>eval</code> implementation:</p>

<ol>

<li>If we eventually want to market our PAC as a stand-alone
application, the incorporation of the whole <em>Scheme</em>
implementation blows up the size of the code immensely.<br><br></li>

<li>When we get to the exact real calculations, our form of evaluation
will be substantially different from <em>Scheme</em>'s, and we won't
gain much by invoking <code>eval</code>---it might even complicate the
structure of our solution.</li>

</ol>

<p>Even when we replace them later, it is a lot easier to construct
software when we have powerful starting points, such as
<code>eval</code>, written by other people that allow us to get the
structure of our code right before we have to fill in all of the
details.</p>

<?php echo html_header($HTML_HEADER_LEVEL + 1,
                       "5. Use a higher-order generic evaluator"); ?>

<p>Rewrite the evaluator using my higher-order generic evaluator,
which you'll find hidden in commented sections of the code. I also
sketched the structure of the solution. Uncomment my stuff, and fill
in where I left ellipses (<code>...</code>).</p>

<p>Although the whole computational structure of the solution is
already there in my <code>generic_evaluate_formula</code>, I expect
that many of you will find it harder to fill in the right arguments to
<code>generic_evaluate_formula</code> for this step than to write your
own recursive code in the previous step. As you get the hang of
higher-order programming, the relative difficulty will shift in favor
of using generic functions.</p>

<p>The reorganization of evaluation to use the generic evaluator also
condenses the information about the formula and value datatypes and
the association of constants and operators with their meanings, so
that it will be easier to update things later on.</p>

<p>One little aspect of the definition of
<code>M-evaluate_formula</code> didn't come out the way I wanted it
to. In principle, we should have written a definition of the form</p>

<blockquote><pre><code>
(define M-evaluate_formula

  ...

  ((generic_evaluate_formula ... ) ...)
  )
</code></pre></blockquote>

<p>instead of</p>

<blockquote><pre><code>
(define (M-evaluate_formula fmla)

  ...

  (((generic_evaluate_formula ... ) ...) fmla)
  )
</code></pre></blockquote>

<p>The mention of the argument <code>fmla</code> is completely
redundant, and disguises the structure of the higher-order definition
a bit. I got stuck with this form because of a syntactic glitch in
<em>Scheme</em> that I consider to be a design error. <em>Scheme</em>
allows local <code>define</code>s at the beginning of a definition
with function arguments, but not at the beginning of a definition with
no function arguments. So, to use the first form of definition, I
would have to change the style of presenting the local definitions
following <code>(define (M-evaluate_formula fmla) ...</code>, which I
judged to be too confusing at this stage.</p>

<?php echo html_header($HTML_HEADER_LEVEL + 1,
                       "6. Correctness, what to hand in"); ?>

<p>In assignments 1-3, if you followed the given structure pretty
closely, and your function definitions computed the right results, you
were probably doing very well. In this assignment, respecting the
abstraction barriers may be more of a problem than getting the right
results. Since <em>Scheme</em> does not enforce abstraction barriers
formally, it is easy to accidentally refer to a specific
implementation where you shouldn't, and still have a working
program. The error bites you later when you change the
implementation. For full credit, you must respect the abstraction
barriers. Read your code carefully to ensure that you do. The trivial
functions, such as <code>M-number-&gt;value</code>, are the easiest to
forget. They might not be trivial in a later version.</p>

<p>You may be able to catch some breaches of the abstraction barrier
by repeating the substitution of a different representation of
formulas from step 3.</p>

<p>Hand in the following:

<ol>

<li>A file named <code>pac.scm</code> containing the final versions
of all the function definitions after step 5 above.<br><br></li>

<li>A file named <code>pac-tst.scm</code> containing a test suite
demonstrating the behavior of the functions you defined.<br><br></li>

<li>A file named <code>pac_varfmla.scm</code> containing a PAC using
your variant version of the formula datatype from step 3. If you
repeated the variation at a later step, you may hand in that version.<br><br></li>

<li>A file named <code>pac_varfmla-tst.scm</code> containing a test
suite demonstrating your variant of the formula datatype. If you test
the formula functions thoroughly, you don't need to test anything on
the other side of the abstraction barrier.<br><br></li>

<li>Optionally, if you have anything to report (including
acknowledgments of where you got ideas), a file named
<code>comments.txt</code> with your comments.</li>

</ol>

<p>If you do not finish, you will get the best partial credit by
handing in a complete working result for step 1, 2, or 4 with
appropriate test suite. There will be much less partial credit for a
dysfunctional and/or untested attempt at a step.</p>

<?php echo html_footer("index", 0, 1); ?>
<!-- hhmts start -->
Last modified: Thu Oct 23 18:48:16 CDT 2003
<!-- hhmts end -->

</body>

</html>
