Debugging programs is an important skill for a computer scientist.
Here are some hints about debugging:
-  Document clearly what each function should do.  Write a comment
(after a semicolon) that states what the function does.
Write a comment describing each argument, unless it is obvious.
Write a comment with an example of a call to the function.
; Compute the value of an investment of a fixed contribution for a
;    given number of time periods at a specified interest rate.
; contribution = amount added at the end of a time period
; time         = number of time periods
; interest     = interest paid per time period, e.g. 6% = 0.06
; Example: (invest 1040 60 0.06)  ; $1040 per year for 60 years at 6%
(define (invest contribution time interest) ...)
 These comments are a  specification of your program.
One source of bugs is an unclear (poorly understood, unwritten) specification.
Sometimes, a clear specification will make it obvious how to write the
program.  One of the best ways to debug is not to write bugs; a good
specification helps.
 
-  Test the function on an easy case first.  Often, the easy case is
the base case of a recursive function.  Make sure the answer is correct
for the easy case.  Then try a slightly harder case -- one for which
you understand the answer.
> (invest 100 0 0.06)
0
> (invest 100 1 0.06)
100.
> (invest 100 2 0.06)
206.
 Investing $100 zero times gives zero.  Investing $100 at the end of one time
period leaves us with the given $100.  Investing $100 for two time periods
gives us interest of $6 on $100 during the second time period.
If your function works on the base case and a few more cases, it probably
works for all cases; if not, it will be easier to understand and fix the
function when the case is an easy one.
 
 
-  Trace your functions.  Use  (trace  fn  ) to
trace the function fn.  You can turn off a trace with
 (untrace  fn).
The trace will show the arguments of a function on entry and the result on
exit.  The entry and exit are matched by vertical alignment of the trace
printouts.
 
-  As soon as you see a bug, track it down and fix it.
Develop a keen eye for anything that looks unusual in your output; if
you see something abnormal, focus on it.
 
-  Test your functions one at a time.
This is easy in Lisp: simply type in a call to a function
with test arguments, even if it is not the ``main'' function.
It is easy to test a single function in isolation, but hard to test a
large system.
 
-  Use rapid prototyping and evolve your programs:
write a program that does part of the job, test it, then expand it.
When you get part of the program working, you can expand
on that model; this is better than repeating the same mistake many times
in your code before doing any testing.
 
-  If your program ``cannot possibly be doing what it is doing'',
the bug is probably something that you are not looking at.  Take a wider
view and look at other things.
 
-  Instrument your code with debugging printouts: print out internal values
and look for abnormalities.  Sometimes students stay up all night trying
to reason about why their program does not work, when a simple printout
would make the problem obvious.
You can detect internal errors and stop your program (and then get variable
values) using an (error   "message") call.
 
   (if stopping-condition
       (error "The elusive bug has occurred!"))
 
-  When you get an error break, DrScheme can provide additional information:
-  Click the function name to get instant documentation of the
function in which the error occurred.
 
-  Click the Bug symbol to get backtrace information.
This will show the sequence of calls that reached the error and
variable values.