Sometimes, computer programs don't work. The best way to fix a broken computer program is to carefully trace through the code to find the flaw. Modular programming, comments in code and indentation can be very helpful when doing this. LOGO also provides the STEP and TRACE commands to help find bugs in code.
The STEP command simply tells LOGO to go through a procedure line by line, so that you won't have to. To use it, type: STEP "PROCEDURENAME, where PROCEDURENAME is the name of the procedure to be traced. For example:
TO SQUARE :SIZE REPEAT 4 [FORWARD :SIZE RIGHT 90] END TO FANCYHOUSE :SIZE SQUARE :SIZE ; Draw the base of the house FD :SIZE RT 30 FD :SIZE RT 120 FD :SIZE ; Draw the roof of the house RT 30 FD :SIZE RT 90 FD :SIZE RT 90 ; Return to starting position RT 90 FD :SIZE/2 RT 180 SQUARE :SIZE/3 ; Draw a door RT 90 PU FD :SIZE/2 PD SQUARE :SIZE/3 ; Draw a window PU BK :SIZE/2 LT 90 FD :SIZE/2 RT 90 PD ; Return to starting position END STEP "FANCYHOUSE FANCYHOUSEAfter typing the commands above, you will be shown each line of code in FANCYHOUSE before the computer runs it. Notice that you are not shown the REPEAT command in the SQUARE procedure; only the lines of FANCYHOUSE are presented for your approval. If you wrote a FANCVILLAGE procedure that used FANCYHOUSE then ran it, you would be allowed to view each line of FANCYHOUSE each time it was run from FANCYVILLAGE. You would not have to approve each line of FANCYVILLAGE unless you chose to STEP through that as well.
After stepping through the FANCYHOUSE procedure a few times, see what changes if you run it after typing STEP "SQUARE. Then write a simple FANCYVILLAGE procedure and run that. If you get tired of hitting enter, type UNSTEP "FANCYHOUSE or UNSTEP "SQUARE to turn off the trace on those procedures.
The procedures below are intended to average the items in a list, but the program is broken. Discuss it with your classmates to find as many errors as you can. If it's still broken once you've fixed those, use STEP to find and fix any remaining errors.
TO AVERAGELIST :LISTNUMS
IF [EMPTY? :LISTNUMS] [PRINT (This list is empty.) STOP]
PRINT FINDAVERAGE LISTNUMS 0
END
TO FINDAVERAGE :LISTNUMS :TOTAL :COUNT
IF EMPTY? :LISTNUMS
[ PRINT (SENTENCE [The average is ] :TOTAL/:COUNT) ]
MAKE :TOTAL :TOTAL + (FIRSTITEM :LISTNUMS)
MAKE :COUNT :COUNT + 1
FINDAVERAGE (BUTFIRST :LISTNUMS) :TOTAL :COUNT
END
STEP is a very useful command that provides comprehensive information about the procedure being traced. Sometimes that much information can be overwhelming. Also, STEP does not always provide the information you need about the values of variables in your procedure.
LOGO's TRACE command can help here. UNSTEP any procedures you've been stepping through and type TRACE "FINDAVERAGE. Then run AVERAGELIST and see what happens.
The TRACE command has one argument: the name of a procedure. When you run a program, TRACE informs you every time that procedure is called and tells you what values its arguments have. It also tells you when that procedure exits. This can be very handy for problem solving in complex programs; for instance, you might want to trace the INSERT procedure in the insertion sort program. As with UNSTEP and STEP, there is an UNTRACE command that tells LOGO to stop listing all the calls to a procedure.
STEP and TRACE are powerful tools for debugging, but sometimes the best tool is the simplest: PRINT. You can add PRINT commands anywhere in your program to let you know when that point has been reached, and what the conditions are at that point. Once your program runs correctly you can delete these, or you can set a flag to turn these print commands on and off as desired. An example of the use of a debugging flag is shown below.
MAKE "DEBUG "FALSE
TO SUMUP :N
MAKE "TOTAL 0
FOR [I 1 :N] ~
[
MAKE "TOTAL :TOTAL+:I
IF :DEBUG [PRINT (SENTENCE [In SUMUP, :I is] :I [and :TOTAL is] :TOTAL)]
]
PRINT (SENTENCE [The sum of the numbers up to] :N [is] :TOTAL)
END
SUMUP 7
Entering the commands above results in the output:
The sum of the numbers up to 7 is 28Running the commands:
MAKE "DEBUG "TRUE SUMUP 5yields:
In SUMUP, :I is 1 and :TOTAL is 1 In SUMUP, :I is 2 and :TOTAL is 3 In SUMUP, :I is 3 and :TOTAL is 6 In SUMUP, :I is 4 and :TOTAL is 10 In SUMUP, :I is 5 and :TOTAL is 15 The sum of the numbers up to 5 is 15The PRINT command inside the FOR loop is executed, because the DEBUG variable has been "turned on".
Of course you don't want to force the people using your program to type MAKE "DEBUG "FALSE every time they load it. This command should be included in the first few lines of the first procedure of the program.