next up previous contents index
Next: Style Guidelines Up: Introductory Scheme Previous: Example Two: Quicksort

Development and Debugging

 

This section describes some techniques the authors have found useful in the development and debugging process.

Unixgif redirection  can be useful in testing programs and producing sample output. As with most applications, XScheme may take its input from a file instead of the keyboard, and may send its output to a file instead of to the screen. File input is especially useful, since it allows one to assemble a file of test cases and redirect them into the interpreter, rather than retyping them every time one wants to test the program. For instance, suppose we have typed the Quicksort program from Section 10.2, and stored it in the file `qsort.scm'. We may test the program, and obtain output for these test cases, by creating a file like the following:

   (load "qsort.scm")
   (transcript-on "qsort.out")
   (qsort '(1 9 5 3 2))
   (qsort '(5 4 3 2 1))
   (qsort '(1 1 2 2 3 3))
   (qsort '(1 2 3 4))
   (transcript-off)
   (exit)
And then, supposing we named this file `qsort.in', we may redirect it into the XScheme interpreter like so:
   % xscheme < qsort.in
Note that the last command in the file is (exit). This exits the XScheme interpreter when the commands in the file is completed. Be careful to include (exit) as the last command in all such test files, as without it, the interpreter will hang, waiting for further input. After this operation completes, the transcript  of the test cases and their output will be in `qsort.out'. Output may also be saved to a file by using redirection rather than transcripting, but this method does not echo the test input to the file, so transcripting is preferred.

Debugging is a little tricky. In a sequential language, one often debugs a program by strategically inserting output statements throughout the program to examine the values of variables, to follow flow of control, and so forth. Scheme lacks this sequentiality, so merely inserting an output statement is impossible. However, Scheme offers a construct that allows such sequential execution, called begin . Its format is merely:

 
		 (begin expression1 expression2 ...expressionN)

In the begin construct, the expressions are evaluated from left to right, and the value of expressionN is returned as the value of the begin construct. One can easily see that such a construct is meaningless unless the first N - 1 expressions have side effects , i.e., they destructively modify the state of some variable (an action that, for our purposes, is considered forbidden) or perform some I/O. This is the purpose for which we will use it: for debugging purposes, we may replace some expression with (begin print-statement expression). This will execute print-statement, then evaluate expression and return its value as the value of the begin; thus, except for the output of print-statement, this modification is transparent in the evaluation of the program.

The output statement in XScheme is merely (write  expression) . This prints the value of expression to the standard output. For example,

 
		 write statement 		 Printed to standard output

(write 13) 13

(write 'a) a

(write "foo") "foo"

(write '(1 2 3)) (1 2 3)

The function (newline) writes a newline character to the standard output.

For example, suppose we replace the entire body of the flatten function described in Section 10.1 with the following:

 
		 (begin (write l1) (newline) body)

Then, when we call the flatten function, we get output something like this:
   > (flatten '((1 (2)) 3 (4) () 5))
   ((1 (2)) 3 (4) () 5)
   (3 (4) () 5)
   ((4) () 5)
   (() 5)
   (5)
   ()
   (4)
   ()
   (1 (2))
   ((2))
   ()
   (2)
   ()
  
   (1 2 3 4 5)
   >

Lastly, it should be noted that Control-C will interrupt the XScheme interpreter and drop you back to the operating system at any time.


next up previous contents index
Next: Style Guidelines Up: Introductory Scheme Previous: Example Two: Quicksort

Steven J. Zeil
Tue Mar 4 14:36:27 EST 1997