When we develop a program, we may hope to implement it with a single
function definition but we should always be prepared to write auxiliary
functions. In particular, if the problem statement mentions several
dependencies, it is natural to express each of them as function. Others who
read the problem statement and the program can follow our reasoning more
easily that way. The movie-theater example in
section~#secbasicscompose#13858> is a good example for this style of
development.
Otherwise, we should follow the design recipe and start with a thorough
analysis of the input and output data. Using the data analysis we should
design a template and attempt to refine the template into a complete
function definition. Turning a template into a complete function
definition means to combine the values of the template's subexpressions
into the final answer. As we do so, we might encounter several different
situations:
- If the formulation of an answer requires a case analysis of the
available values, use a <#62939#><#13860#>cond<#13860#>-expression<#62939#>.
- If a computation requires knowledge of a particular domain of
application, for example, drawing on (computer) canvases, accounting,
music, science, use an auxiliary function.
- If a computation must process a list, a natural number, or some other
piece of data of arbitrary size, use an auxiliary function.
- If the natural formulation of the function isn't quite what we want,
it is most likely a generalization of our target. In this case, the main
function is a short definition that defers the computation to the
generalized auxiliary program.
The last two criteria are situations that we haven't discussed yet. The
following two subsections illustrate them with examples.
After we determine the need for an auxiliary function, we should add a
contract, a header, and a purpose statement to a <#62940#><#13862#>WISH LIST<#13862#><#62940#> of
functions.
rawhtml22 Guideline on Wish Lists rawhtml23 Maintain a list of functions that must be developed to complete a program. Develop each function according to a design recipe. rawhtml24
Before we put a function on the wish list, we must check whether
something like the function already exists or is already on the wish
list. Scheme provides many primitive operations and functions, and so do
other languages. We should find out as much as possible about our working
language, though only when we settle on one. For beginners, a superficial
knowledge of a language is fine.
If we follow these guidelines, we interleave the development of one
function with that of others. As we finish a function that does not depend
on anything on our wish list, we can test it. Once we have tested such
basic functions, we can work our way backwards and test other functions
until we have finished the wish list. By testing each of a function
rigorously before we test those that depend on it, we greatly reduce the
effort of searching for logical mistakes.