Documenting Your Procedures
Convention in Scheme (and all programming languages) is that we carefully
document what our procedures do, including input values, output values,
and assumptions. We use comments provide information to the reader of
our program (that is, to people instead of the computer). In Scheme,
comments begin with a semicolon and end with the end of the line.
There are a variety of kinds of comments we write. For now, we'll focus
on the comments we write for the other programmers who might call the
procedures we write.
Documenting the square Procedure
Let's consider the documentation that we wrote for the
square procedure that was
introduced in the
first reading on procedures.
;;; Samuel A. Rebelsky and Janet Davis
;;; Department of Computer Science
;;; Grinnell College
;;; {rebelsky,davisjan}@grinnell.edu
;;; Procedure:
;;; square
;;; Parameters:
;;; val, a number
;;; Purpose:
;;; Compute val*val
;;; Produces:
;;; result, a number
;;; Preconditions:
;;; val must be a number
;;; Postconditions:
;;; result is the same "type" of number as val (e.g., if
;;; val is an integer, so is result; if val is exact,
;;; so is result).
;;; Citations:
;;; Based on code created by John David Stone dated March 17, 2000
;;; and contained in the Web page
;;; http://www.math.grin.edu/~stone/courses/scheme/procedure-definitions.xhtml
;;; Changes to
;;; Parameter names
;;; Formatting
;;; Comments
(define square
(lambda (value)
(* value value)))
Yes, that's a lot of documentation for very little code. However, it
is better to err on the side of too much documentation than too little
documentation. More importantly, as you start writing more procedures,
their purpose and details will be much less obvious when you come back
to them. Finally, when you carefully document procedures, you begin
to think more carefully about what they really need to do and how you
ensure that they do so for all cases.
Another Example: Grading Homework
The square computation is fairly simple. We can, of course, write
more complex expressions. For example, consider the problem of
generating an average numeric grade, given a six grades (on exams,
quizzes, whatever). A pure average would simply add the six numbers
together and divide by six.
A more generous policy for dealing with such grades
would be to drop the lowest grade and count the highest grade twice.
We might express that policy as
Of course, it would be nice to make this procedure work with a varying
number of homework grades. We'll see one such strategy in a few days,
when we begin to explore lists.
Documenting the compute-grade Procedure
We just described a variety of
compute-grade procedures. Believe
it or not, but we can write a common set of documentation for them:
It turns out that writing this documentation helped us think a bit more
about some particular issues that relate to the procedure. For example,
we needed to specify something about the result that the client would
find useful. At the same time, we wanted to keep the documentation
general enough that we could use either policy. That made us decide that
putting limits on the result was appropriate. Those limits are, however
limiting. We cannot, for example, write a procedure that gives as
student who does every assignment a bit of extra credit, since that might
lead to a grade higher than any given so far.
We also had to specify that the procedure took numbers as inputs and
produced a number. Without such consideration, we might have had an
awkward moment in which someone called our procedure with letter grades,
or expected it to return a letter grade.