about summary refs log tree commit diff stats
path: root/js/games/nluqo.github.io/~bh/v1ch15
diff options
context:
space:
mode:
authorelioat <elioat@tilde.institute>2023-08-23 07:52:19 -0400
committerelioat <elioat@tilde.institute>2023-08-23 07:52:19 -0400
commit562a9a52d599d9a05f871404050968a5fd282640 (patch)
tree7d3305c1252c043bfe246ccc7deff0056aa6b5ab /js/games/nluqo.github.io/~bh/v1ch15
parent5d012c6c011a9dedf7d0a098e456206244eb5a0f (diff)
downloadtour-562a9a52d599d9a05f871404050968a5fd282640.tar.gz
*
Diffstat (limited to 'js/games/nluqo.github.io/~bh/v1ch15')
-rw-r--r--js/games/nluqo.github.io/~bh/v1ch15/debug.html713
1 files changed, 713 insertions, 0 deletions
diff --git a/js/games/nluqo.github.io/~bh/v1ch15/debug.html b/js/games/nluqo.github.io/~bh/v1ch15/debug.html
new file mode 100644
index 0000000..f5f31c0
--- /dev/null
+++ b/js/games/nluqo.github.io/~bh/v1ch15/debug.html
@@ -0,0 +1,713 @@
+<HTML>
+<HEAD>
+<TITLE>Computer Science Logo Style vol 1 ch 15: Debugging</TITLE>
+</HEAD>
+<BODY>
+<CITE>Computer Science Logo Style</CITE> volume 1:
+<CITE>Symbolic Computing</CITE> 2/e Copyright (C) 1997 MIT
+<H1>Debugging</H1>
+
+<TABLE width="100%"><TR><TD>
+<IMG SRC="../csls1.jpg" ALT="cover photo">
+<TD><TABLE>
+<TR><TD align="right"><CITE><A HREF="http://www.cs.berkeley.edu/~bh/">Brian
+Harvey</A><BR>University of California, Berkeley</CITE>
+<TR><TD align="right"><BR>
+<TR><TD align="right"><A HREF="../pdf/v1ch15.pdf">Download PDF version</A>
+<TR><TD align="right"><A HREF="../v1-toc2.html">Back to Table of Contents</A>
+<TR><TD align="right"><A HREF="../v1ch14/v1ch14.html"><STRONG>BACK</STRONG></A>
+chapter thread <A HREF="../v1ch16/versions.html"><STRONG>NEXT</STRONG></A>
+<TR><TD align="right"><A HREF="https://mitpress.mit.edu/books/computer-science-logo-style-second-edition-volume-1">MIT
+Press web page for Computer Science Logo Style</A>
+</TABLE></TABLE>
+
+<HR>
+
+
+<P>
+I haven't talked much, until now, about how to find and fix mistakes
+in the programs you write.  Except for the chapter-length examples
+in Chapters 6, 12, and 14, it hasn't been much of a
+problem because the sample programs I've shown you have been so
+small.  That doesn't mean you can't make a mistake in a small program!
+But mistakes are relatively easy to find when the entire program is
+one procedure with just a few instruction lines.  In a real
+programming project, which might have 20 or 200 procedures, it's harder
+to locate an error.
+
+<P><H2>Using Error Messages</H2>
+
+<P>At one point in Chapter 13 I saw the error message
+
+<P><PRE>I don't know how  to one  in pokerhand
+</PRE>
+
+<P>Logo's error messages were deliberately designed to use an
+informal, smooth, low-key style so that beginning programmers won't
+find them intimidating.  But there is a lot of information in that
+message if you learn how to find it.  The message tells me three
+things.  First, it tells me what <EM>kind</EM> of error is involved.
+In this particular message,
+the phrase &quot;I don't know how&quot; suggests that a procedure is missing,
+and the words &quot;to one&quot; subtly suggest how the problem could be fixed.
+Second, the message tells me the <EM>specific</EM> expression that was
+in error: the word <CODE>one</CODE>.  Third, it tells me that the error was
+detected while Logo was carrying out the procedure named <CODE>
+pokerhand</CODE>.
+
+<P>The precise form of the message may be different in different situations.
+If you make a mistake in a top-level instruction (that is, one that you type
+to a question mark prompt, not inside a procedure), the part about <CODE>in
+pokerhand</CODE> won't be included.
+
+<P>One very important thing to remember is that the place where an error
+is <EM>found</EM> may not be the place where the error really <EM>
+is.</EM>  That's a little vague, so let's think about the <CODE>I don't know
+how</CODE> error.  All the Logo interpreter knows is that it has been
+asked to invoke a procedure that doesn't exist.  But there can be
+several possible reasons for that.  The most common reason is that
+you've just misspelled the name of a procedure.  When the message is
+
+<P><PRE>I don't know how  to forwrad  in poly
+</PRE>
+
+<P>you can be pretty sure, just from reading the message, that
+the problem is a misspelling of <CODE>forward</CODE>.  In this case the
+mistake is in <CODE>poly</CODE>, just as the message tells you.
+
+<P>On the other hand you might get a message like this about a procedure
+that really should exist.  For example, I might have seen
+
+<P><PRE>I don't know how  to straight  in pokerhand
+</PRE>
+
+<P>If I had been confronted with that message, I might have
+looked at <CODE>pokerhand</CODE>, and indeed I would have found an
+instruction that invokes a procedure named <CODE>straight</CODE>.  But
+that's not an error; there <EM>should</EM> be such a procedure.  One of
+two things would be wrong: either I'd forgotten to define <CODE>
+straight</CODE> altogether or else I made a spelling mistake in the title
+line of <CODE>straight</CODE> rather than in an instruction line of <CODE>
+pokerhand</CODE>.  To find out, I would type the command <CODE>pots</CODE> (which,
+as you recall, stands for Print Out TitleS) and look for a possible
+misspelling of <CODE>straight</CODE>.
+
+<P>Another way to get the same error message is to write a program using one
+version of Logo and then transfer it to another version with somewhat
+different primitives.  For example, Berkeley Logo includes higher order
+functions such as <CODE>map</CODE> that are not primitive in most other Logo
+dialects.  If you write a program that uses <CODE>map</CODE> and then try to run it
+in another version of Logo, you'll get a message saying <CODE>I don't know
+how to map</CODE>.  In that case you'd have to write your own version of <CODE>
+map</CODE> or rewrite the program to avoid using it--for example, by using a
+recursive operation instead.
+
+<P>The mistake I actually made in Chapter 13 wasn't a misspelling, a
+missing definition, or a nonexistent primitive.  Instead, I failed to
+quote a list with square brackets.  The particular context in which I
+did it, in an input to <CODE>ifelse</CODE>, is a fairly obscure one.  But
+here is a common beginner's mistake, especially for people who are
+accustomed to other programming languages:
+
+<P><PRE>? <U>print &quot;How are you?&quot;</U>
+How
+i don't know how  to are
+</PRE>
+
+<P>The moral of all this is that the error message <EM>does</EM> give you
+some valuable help in finding your bug, but it <EM>doesn't</EM> tell
+you the whole story.  You have to read the message intelligently.
+
+<P><H2>Invalid Data</H2>
+
+<P>I've spent a lot of time on the <CODE>I don't know how</CODE> message because
+it's probably the most common one.  Another very common kind of
+message, which will merit some analysis here, is
+
+<P><PRE><U>procedure</U> doesn't like <U>datum</U> as input
+</PRE>
+
+<P>In general, this means that you've violated the rules about
+the kinds of data that some primitive procedure requires as
+input.  (Recall that the type of input is one of the things I've been
+insisting that you mention as part of the description of a procedure.)
+For example, <CODE>word</CODE> requires words as inputs, so:
+
+<P><PRE>? <U>print word &quot;hello, [old buddy]</U>
+word doesn't like [old buddy] as input
+</PRE>
+
+<P>There are several special cases, however, that come up more often
+than something as foolish as using a list as an input to <CODE>word</CODE>.
+The most common message of this form is this one:
+
+<P><PRE>butfirst doesn't like [] as input
+</PRE>
+
+<P>This almost invariably means that you've left out the
+stop rule in a recursive
+procedure.  The offending input to <CODE>butfirst</CODE> isn't
+an explicit empty list but instead is the result of evaluating
+a variable, usually an input to the
+procedure you're writing, that's <CODE>butfirst</CODE>ed in the recursive
+invocation.  This is a case where the error isn't really in the
+instruction that caused the message.  Usually there is nothing wrong
+with the actual invocation of <CODE>butfirst</CODE>; the error is a missing
+instruction earlier in the procedure.  If the input is a
+word instead of a list, this message will take the possibly confusing
+form
+
+<P><PRE>butfirst doesn't like  as input
+</PRE>
+
+<P>That's an invisible empty word between <CODE>like</CODE> and <CODE>
+as</CODE>!
+
+<P>I said that this message is almost always caused by a missing stop
+rule.  You have to be careful about the &quot;almost.&quot; For example,
+recall this practical joke procedure from Chapter 1:
+
+<P><PRE>to process :instruction
+test emptyp :instruction
+iftrue [type &quot;|? | process readlist stop]
+iffalse [print sentence [|I don't know how  to|] first :instruction]
+end
+</PRE>
+
+<P>This is not a recursive procedure, and the question of stop
+rules doesn't arise.  But its input might be empty, because the victim
+enters a blank line.  If I hadn't thought of that, and had written
+
+<P><PRE>to process :instruction
+print sentence [|I don't know how  to|] first :instruction
+end
+</PRE>
+
+<P>the result would be
+
+<P><PRE>first doesn't like [] as input  in process
+</PRE>
+
+<P>Another case that sometimes comes up in programs that do arithmetic is
+
+<P><PRE>/ doesn't like 0 as input
+</PRE>
+
+<P>For example, if you write a program that takes the average
+of a bunch of numbers and you try to use the program with an empty
+list of numbers as input, you'll end up trying to divide zero by
+zero.  The solution is to insert an instruction that explicitly tests
+for that possibility.
+
+<P>As always, the procedure that provokes the error message may not
+actually be the procedure that is in error.  Consider this short
+program:
+
+<P><PRE>to second :thing
+output first butfirst :thing
+end
+
+to swap :list
+output list (second :list) (first :list)
+end
+
+? <U>print swap [watch pocket]</U>
+pocket watch
+? <U>print swap [farewell]</U>
+first doesn't like [] as input  in second
+[output first butfirst :thing]
+</PRE>
+
+<P>Although the error was caught during the invocation of <CODE>
+second</CODE>, there is nothing wrong with <CODE>second</CODE> itself.  The error
+was in the top-level instruction, which provided a bad input to <CODE>
+swap</CODE>.  That instruction doesn't even include an explicit reference to
+<CODE>second</CODE>.  In this small example it's easy to see what happened.  But
+in a more complicated program it can be hard to find errors like this
+one.
+
+<P>There are two ways you can protect yourself against this kind of
+difficulty.  The first is <EM>defensive programming.</EM>  I could have
+written the program this way:
+
+<P><PRE>to swap :list
+if emptyp :list [pr [empty input to swap] stop]
+if emptyp butfirst :list [pr [singleton input to swap] stop]
+output list (second :list) (first :list)
+end
+</PRE>
+
+<P>This version checks for bad inputs and gives a more helpful
+error message.*Actually, when you invoke this version of
+<CODE>swap</CODE> with a bad input, you'll see <EM>two</EM> error messages.
+The procedure itself will print an error message.  Then, since it <CODE>
+stop</CODE>s instead of <CODE>output</CODE>ting something to its superprocedure,
+you'll get a <CODE>didn't output</CODE> error message from the Logo
+interpreter.  It would also be possible to figure out an appropriate
+output for these cases and not consider them errors at all:
+
+<P><PRE>to swap :list
+if emptyp :list [output []]
+if emptyp butfirst :list [output :list]
+output list (second :list) (first :list)
+end
+</PRE>
+
+<P>This version manages to produce an output for any input at
+all.  How should you choose between these two defensively written
+versions?  It depends on the context in which you'll be using <CODE>
+swap</CODE>.  If you are writing a program in which <CODE>swap</CODE> should always
+get a particular kind of list as input, which should always have two
+members, then you should use the first defensive version, which will
+let you know if you make an error in the input to <CODE>swap</CODE>.  But if
+<CODE>swap</CODE> is intended as a general tool, which might be used in a
+variety of situations, it might be better to accept any input.
+
+<P>The second protective technique, besides defensive programming, is
+tracing, the technique we used in Chapter 9.  If you get an
+error message from a utility procedure like <CODE>second</CODE> and you have no
+idea how it was invoked, you can find out by tracing the entry into all of
+your procedures.
+
+<P>Another way to get the <CODE>doesn't like</CODE> message is to forget the
+order of inputs to a procedure, either a primitive or one that you've
+written.  For example, <CODE>lput</CODE> is a primitive operation that
+requires two inputs.  The first input can be any datum, but the
+second must be a list.  The output from <CODE>lput</CODE> is a list that
+contains all the members of the second input, plus one more member at
+the end equal to the first input.
+
+<P><PRE>? <U>show lput &quot;c [a b]</U>
+[a b c]
+</PRE>
+
+<P><CODE>Lput</CODE> takes its inputs in the same order as <CODE>fput</CODE>,
+with the new member first and then the old list.  But you might get
+confused and want the inputs to appear left-to-right as they appear in
+the result:
+
+<P><PRE>? <U>show lput [a b] &quot;c</U>
+lput doesn't like c as input
+</PRE>
+
+<P><H2>Incorrect Results</H2>
+
+<P>Beginning programmers are often dismayed when they see an error
+message, but more experienced programmers are relieved.  They know
+that the bugs that cause such messages are the easy ones to find!  Much
+harder are the bugs that allow a program to run to completion but
+produce the wrong answer.  In that kind of situation you don't have
+the advantage of knowing which procedure tickled the error message, so
+it's hard to know where to begin looking.
+
+<P>Here's a short program with a couple of bugs in it.  <CODE>Arabic</CODE> is an
+operation that takes one input, a word that is a Roman numeral.
+The output from <CODE>arabic</CODE> is the number represented by that Roman numeral
+in ordinary (Arabic numeral) notation.
+
+<P><PRE>to arabic :num
+output addup map &quot;digit :num
+end
+
+to digit :digit
+output lookup :digit [[I 1] [V 5] [X 10] [L 50] [C 100] [D 500] [M 1000]]
+end
+
+to lookup :word :dictionary
+if emptyp :dictionary [output &quot;]
+if equalp :word first first :dictionary [output last first :dictionary]
+output lookup :word bf :dictionary
+end
+
+to addup :list
+if emptyp :list [output 0]
+if emptyp bf :list [output first :list]
+if (first :list) &lt; (first bf :list) ~
+   [output sum ((first bl :list)-(first :list)) addup bf bf :list]
+output sum first :list addup bf :list
+end
+</PRE>
+
+<P><CODE>Arabic</CODE> uses two non-primitive subprocedures, dividing its
+task into two parts.  First <CODE>digit</CODE> translates each letter of the Roman
+numeral into the number it represents: <CODE>C</CODE> into 100, <CODE>M</CODE> into 1000.
+The result is a list of numbers.  Then <CODE>addup</CODE> translates that list into
+a single number, adding or subtracting each member as appropriate.  The rule
+is that the numbers are added, except that a smaller number that appears to
+the left of a larger one is subtracted from the total.  For example, in the
+Roman numeral <CODE>CLIV</CODE> all the letters are added except for the <CODE>I</CODE>,
+which is to the left of the <CODE>V</CODE>.  Since <CODE>I</CODE> represents 1 and
+<CODE>V</CODE> represents 5, and 1 is less than 5, the <CODE>I</CODE> is subtracted.  The
+result is 100+50+5-1 or 154.
+
+<P>Here's what happened the first time I tried <CODE>arabic</CODE>:
+
+<P><PRE>? <U>print arabic &quot;MLXVI</U>
+13
+</PRE>
+
+<P>This is a short enough program that you may be able to find the bug
+just by reading it.  But even if you do, let's pretend that you don't,
+because I want to use this example to talk about some ways of looking
+for bugs systematically.
+
+<P>The overall structure of the program is that <CODE>digit</CODE> is invoked for each
+letter, and the combined output from all the calls to <CODE>digit</CODE> is used as
+the input to <CODE>addup</CODE>.  The first step is to try to figure out which of
+the two is at fault.  Which should we try first?  Since <CODE>addup</CODE> depends
+on the work of <CODE>digit</CODE>, whereas <CODE>digit</CODE> doesn't depend on <CODE>
+addup</CODE>, it's probably best to start with <CODE>digit</CODE>.  So let's try looking
+at the output from <CODE>digit</CODE> directly.
+
+<P><PRE>? <U>print digit &quot;M</U>
+1000
+? <U>print digit &quot;V</U>
+5
+</PRE>
+
+<P>So far so good.  Perhaps the problem is in the way <CODE>map</CODE> is
+used to combine the results from <CODE>digit</CODE>:
+
+<P><PRE>? <U>show map &quot;digit &quot;MLXVI</U>
+1000501051
+</PRE>
+
+<P>Aha!  I wanted a list of numbers, one for each Roman digit,
+but instead I got all the numbers combined into one long word.  I had
+momentarily forgotten that if the second input to <CODE>map</CODE> is a word,
+its output will be a word also.  As soon as I see this, the solution
+is apparent to me:  I should use <CODE>map.se</CODE> instead of <CODE>map</CODE>.
+
+<P><PRE>? <U>show map.se &quot;digit &quot;MLXVI</U>
+[1000 50 10 5 1]
+
+to arabic :num
+output addup map.se &quot;digit :num
+end
+
+? <U>print arabic &quot;MLXVI</U>
+1066
+</PRE>
+
+<P>This time I got the answer I expected.  On to more
+test cases:
+
+<P><PRE>? <U>print arabic &quot;III</U>
+3
+? <U>print arabic &quot;XVII</U>
+17
+? <U>print arabic &quot;CLV</U>
+155
+? <U>print arabic &quot;CLIV</U>
+150
+?
+</PRE>
+
+<P>Another error!  The result was 150 instead of the correct 154.
+Since the other three examples are correct, the program is not
+completely at sea; it's a good guess that the bug has to do with the
+case of subtracting instead of adding.  Trying a few more examples
+will help confirm that guess.
+
+<P><PRE>? <U>print arabic &quot;IV</U>
+0
+? <U>print arabic &quot;MCM</U>
+1000
+? <U>print arabic &quot;MCMLXXXIV</U>
+1080
+? <U>print arabic &quot;MDCCLXXVI</U>
+1776
+?
+</PRE>
+
+<P>Indeed, numbers that involve subtraction seem to fail,
+while ones that are purely additive seem to work.  If you look
+carefully at exactly <EM>how</EM> the program fails, you may notice
+that the letter that should be subtracted and the one after it are
+just ignored.  So in the numeral <CODE>MCMLXXXIV</CODE>, which represents 1984, the
+<CODE>CM</CODE> and the <CODE>IV</CODE> don't contribute to the program's result.
+
+<P>Once again, we must find out whether the bug is in <CODE>digit</CODE> or in <CODE>
+addup</CODE>, and it makes sense to start by checking the one that's called first.
+(If you read the instructions in the definitions of <CODE>digit</CODE> and <CODE>
+addup</CODE>, you'll see that <CODE>digit</CODE> handles each digit in isolation, whereas
+<CODE>addup</CODE> is the one that looks at two consecutive digits to decide whether
+or not to subtract.  But at first I'm not reading the instructions at all;
+I'm trying to be sure that I understand the <EM>behavior</EM> of each
+procedure before I look inside any of them.  For a simple problem like this
+one, the approach I'm using is more ponderous than necessary.  But it would
+pay off for a larger program with more subtle bugs.)
+
+<P><PRE>? <U>show map.se &quot;digit &quot;VII</U>
+[5 1 1]
+? <U>show map.se &quot;digit &quot;MDCCLXXVI</U>
+[1000 500 100 100 50 10 10 5 1]
+</PRE>
+
+<P>I've started with Roman numerals for which the overall program
+works.  Why not just concentrate on the cases that fail?  Because I want to
+see what the <EM>correct</EM> output from <CODE>map</CODE>ping <CODE>digit</CODE> over the
+Roman numeral is supposed to look like.  It turns out to be a list of
+numbers, one for each letter in the Roman numeral.
+
+<P>You may wonder why I need to investigate the correct behavior of <CODE>
+digit</CODE> experimentally.  If I've planned the program properly in the
+first place, I should <EM>know</EM> what it's supposed to do.  There
+are several reasons why I might feel a need for this sort of
+experiment.  Perhaps it's someone else's program I'm debugging, and I
+don't know what the plan was.  Perhaps it's a program I wrote a long
+time ago and I've forgotten.  Finally, since there is a bug after
+all, perhaps my understanding is faulty even if I do think I know what
+<CODE>digit</CODE> is supposed to do.
+
+<P>Now let's try <CODE>digit</CODE> for some of the buggy cases.
+
+<P><PRE>? <U>show map.se &quot;digit &quot;IV</U>
+[1 5]
+? <U>show map.se &quot;digit &quot;MCMLXXXIV</U>
+[1000 100 1000 50 10 10 10 1 5]
+?
+</PRE>
+
+<P><CODE>Digit</CODE> still does the right thing:  It outputs the number
+corresponding to each letter.  The problem must be in <CODE>addup</CODE>.
+
+<P>Now it's time to take a look at <CODE>addup</CODE>.  There are four
+instructions in its definition.  Which is at fault?  It must be one
+that comes into play only for the cases in which subtraction is
+needed.  That's a clue that it will be one of the <CODE>if</CODE>
+instructions, although instructions that aren't explicitly
+conditional can, in fact, depend on earlier <CODE>if</CODE> tests.  (In this
+procedure, for example, the last instruction doesn't look
+conditional.  But it is carried out only if none of the earlier
+instructions results in an <CODE>output</CODE> being evaluated.)
+
+<P>Rather than read every word of every line carefully, we should start
+by knowing the purpose of each instruction.  The first one is an end
+test, detecting an empty numeral.  The second is also an end test,
+detecting a single-digit numeral.  (Why are two end tests necessary?
+How would the program fail if each one were eliminated?) The third
+instruction deals with the subtraction case, and the fourth with the
+addition case.  The bug, then, is probably in the third instruction.
+Here it is again:
+
+<P><PRE>if (first :list) &lt; (first bf :list) ~
+   [output sum ((first bl :list)-(first :list)) addup bf bf :list]
+</PRE>
+
+<P>At this point a careful reading of the instruction will
+probably make the error obvious.  If not, look at each of the
+expressions used within the instruction, like
+
+<P><PRE>first :list
+</PRE>
+
+<P>and
+
+<P><PRE>bf bf :list
+</PRE>
+
+<P>What number or list does each of them represent?
+
+<P>(If you'd like to take time out for a short programming project now,
+you might try writing <CODE>roman</CODE>, an operation to translate in the
+opposite direction, from Arabic to Roman numerals.  The rules are that
+<CODE>I</CODE> can be subtracted from <CODE>V</CODE> or <CODE>X</CODE>; <CODE>X</CODE> can be
+subtracted from <CODE>L</CODE> or <CODE>C</CODE>; and <CODE>C</CODE> can be subtracted from
+<CODE>D</CODE> or <CODE>M</CODE>.  You should never need to repeat any symbol more
+than three times.  For example, you should use <CODE>IV</CODE> rather than
+<CODE>IIII</CODE>.)
+
+<P><H2>Tracing and Stepping</H2>
+
+<P>In Chapter 9 we used the techniques of <EM>tracing</EM> and <EM>
+stepping</EM> to help you understand how recursive procedures work.  The
+same techniques can be very valuable in debugging.  Tracing a
+procedure means making it print an indication of when it starts and
+stops.  Stepping a procedure means making it print each of its
+instructions and waiting for you to type something before evaluating
+the instruction.
+
+<P>Berkeley Logo provides primitive commands <CODE>trace</CODE> and
+<CODE>step</CODE> that automatically trace or step procedures for you.  <CODE>
+Trace</CODE> and <CODE>step</CODE> take one input, which can be either a word or a
+list.  If the input is a word, it must be the name of a procedure.  If
+a list, it must be a list of words, each of which is the name of a
+procedure.  The effect of <CODE>trace</CODE> is to modify the procedure or
+procedures named in the input to identify the procedure and its inputs
+when it is invoked.  The effect of <CODE>step</CODE> is to modify the named
+procedure(s) so that each instruction is printed before being
+evaluated.
+
+<P>Tracing a procedure is particularly useful in the annoying situation in
+which a program just sits there forever, never stopping, but never printing
+anything either.  This usually means that there is an error in a recursive
+procedure, which invokes itself repeatedly with no stop rule or with an
+ineffective one.  If you trace recursive procedures, you can find out how
+you got into that situation.
+
+<P>
+<H2>Pausing</H2>
+
+<P>When a program fails, either with an error message or by printing the
+wrong result, it can be helpful to examine the values of the variables
+used within the program.  Of course, you understand by now that &quot;the
+variables used within the program&quot; may be a complicated idea; if
+there are recursive procedures with local variables, there may be
+several variables with the same name, one for each invocation of a
+procedure.
+
+<P>Once a program is finished running, the local variables created by the
+procedures within the program no longer exist.  You can examine global
+variables individually by <CODE>print</CODE>ing their values or all at
+once with the <CODE>pons</CODE> command.  (<CODE>Pons</CODE> stands for Print Out
+NameS; it takes no inputs and prints the names and values of
+all current variables.)  But it's too late to examine local variables
+after a program stops.
+
+<P>To get around this problem, Berkeley Logo provides
+a <CODE>pause</CODE> command.  This command takes
+no inputs.  Its effect is to stop,
+temporarily, the procedure in which it appears.  (Like <CODE>stop</CODE> and
+<CODE>output</CODE>, <CODE>pause</CODE> is meaningless at top level.)  Logo prints a
+question mark prompt (along with the name of the paused procedure
+to remind you that it's paused), and you can enter instructions to be evaluated
+as usual.  But the paused procedure is <EM>still active;</EM> its local
+variables still exist.  (Any superprocedures of the paused procedure,
+naturally, are also still active.)  The instructions you type while the
+procedure is paused can make use of local variables, just as if the
+instructions appeared within the procedure definition.
+
+<P>The main use of <CODE>pause</CODE> is for debugging.  If your program dies
+with an error message you don't understand, you can insert a <CODE>
+pause</CODE> command just before the instruction that gets the error.  Then
+you can examine the variables that will be used by that instruction.
+
+<P>Better yet, you can ask Logo to pause <EM>automatically</EM> whenever
+an error occurs.  In fact, you can ask Logo to carry out any instructions
+you want, whenever an error occurs, by creating a variable named <CODE>erract</CODE>
+(short for error action) whose value is an instruction list.  If you want
+your program to pause at any error, say
+
+<P><PRE>? <U>make &quot;erract [pause]</U>
+</PRE>
+
+<P>before you run the program.  To undo this request, you can
+erase the variable name <CODE>erract</CODE> with the <CODE>ern</CODE> (erase name)
+command:
+
+<P><PRE>? <U>ern &quot;erract</U>
+</PRE>
+
+<P>Once you've examined the relevant variables, you may want to continue
+running the program.  You'll certainly want to continue if this pause
+wasn't the one you're waiting for, just before the error happens.
+Logo provides the command <CODE>continue</CODE> (abbreviated <CODE>co</CODE>) for this
+purpose.  If you type <CODE>continue</CODE> with no input, Logo will continue the
+evaluation of the paused procedure where it left off.
+
+<P>It is also
+possible to use <CODE>continue</CODE> with an input, turning the <CODE>pause</CODE>
+command into an operation by providing a value for it to output.  Whether
+or not that's appropriate depends on which error message you get.  If
+the message complains about a missing value, you may be able to provide
+one to allow the program to continue:
+
+<P><PRE>to demo.error
+print first :nonesuch
+end
+
+? <U>make &quot;erract [pause]</U>
+? <U>demo.error</U>
+nonesuch has no value  in demo.error
+[print first :nonesuch]
+Pausing...
+demo.error? <U>continue &quot;hello</U>
+h
+</PRE>
+
+<P>If, after examining variables, you figure out the reason for the bug,
+you may not want to bother continuing the buggy procedure.  Instead
+you'll want to forget about it, edit the definition to fix the bug,
+and try again.  But you shouldn't just forget about it because the
+procedure is still active.  If you don't want to continue it, you
+should <CODE>stop</CODE> it instead, to get back to the &quot;real&quot; top level
+with no procedures active.  (Instead of <CODE>stop</CODE>, a more definitive
+way to stop all active procedures is with the instruction
+
+<P><PRE>throw &quot;toplevel
+</PRE>
+
+<P>For now just think of this as a magic incantation; we'll talk more
+about <CODE>throw</CODE> in the second volume.)
+
+<P>Berkeley Logo also has a special character
+that you can type on the keyboard to cause an immediate pause.  The
+character depends on which computer you're using; see Appendix A.
+This is not as useful a capability as
+you might think because it's hard to synchronize your typing with the
+activity of the program so that it gets paused in the right <EM>
+context</EM> (that is, with the right procedures active and the right
+local variables available).  But it can be useful if you can see that
+the program is repeating the same activities over and over, for
+example; pausing just about anywhere during that kind of <EM>loop</EM>
+is likely to give you useful information.
+
+<P><H2>Final Words of Wisdom</H2>
+
+<P>You may be feeling a frustrating sense of incompleteness about this
+chapter.  After the chapter on variables, for example, you really knew
+everything there is to know about variables.  (I suppose that's not
+strictly true, since you hadn't thought about recursion yet, but it's
+true enough.)  But you certainly don't know everything there is to know
+about debugging.  That's because there isn't a complete set of rules
+that will get you through every situation.  You just have to do a lot
+of programming, meet a lot of bugs, and develop an instinct for them.
+
+<P>As a beginner, you'll probably meet bugs with a different flavor from
+the ones I've been discussing.  You'll put a space after a quotation
+mark or a colon, before the word to which it should be attached.
+You'll leave out a left or right parenthesis or bracket.  (Perhaps
+you'll get confused about when to use parentheses and when brackets!)
+All of these simple errors will quickly get you error messages, and
+you can probably find your mistake just by reading the offending
+instruction.  Later, as your programs get more complicated, you'll
+start having the more interesting bugs that require analysis to find
+and fix.
+
+<P>It's a good idea to program with a partner.  Sometimes you can find
+someone else's bugs more easily than your own--when you read
+your own program, you know too well what you <EM>meant</EM> to say.
+This advice is not just for beginners; even experienced programmers
+often benefit from sharing their bugs with a friend.  Another
+advantage of such a partnership is that trying to explain your program
+to someone else will often help you understand it more clearly
+yourself.  I've often discovered a persistent bug halfway through
+explaining the problem to someone.
+
+<P>The main point, I think, is one I've made in earlier chapters: there
+is nothing shameful about a bug in your program.  As a teacher, I've
+been astonished to see students react to a simple bug by angrily
+erasing an entire program, which they'd spent hours writing!  Teach
+yourself to expect bugs and approach them with a good-natured spirit.
+
+<P>On the other hand, you can minimize your debugging time by writing the
+program in a reasonable style in the first place.  If your program is
+one long procedure, you should know that you're making it harder to
+locate an offending instruction.  If all your variables are named <CODE>
+x</CODE> and <CODE>y</CODE>, you deserve whatever happens to you!  And if you can't
+figure out, yourself, which procedure does what, then perhaps you
+should stop typing in procedures and spend a little time with paper
+and pencil listing the tasks each procedure needs to carry out.
+
+<P><A HREF="../v1-toc2.html">(back to Table of Contents)</A>
+<P><A HREF="../v1ch14/v1ch14.html"><STRONG>BACK</STRONG></A>
+chapter thread <A HREF="../v1ch16/versions.html"><STRONG>NEXT</STRONG></A>
+
+<P>
+<ADDRESS>
+<A HREF="../index.html">Brian Harvey</A>, 
+<CODE>bh@cs.berkeley.edu</CODE>
+</ADDRESS>
+</BODY>
+</HTML>