Hi all,
I am using the clisp interpretter avaliable with cygwin. I am
new to the language. I would like to know how to use the debugger,
everytime I make a mistake it takes me to the debugger I dont know how
to proceed.
Thanks
Sledge
csledge wrote:
> Hi all,
> I am using the clisp interpretter avaliable with cygwin. I am
> new to the language. I would like to know how to use the debugger,
> everytime I make a mistake it takes me to the debugger I dont know how
> to proceed.
A lot of times you can just look at the error message and figure out
what you did wrong -- Lisp error messages, unlike with some other
languages, actually tell you precisely what you did wrong -- and then
you just abort or cancel the backtrace and go back to work.
Otherwise, the CLisp manual probably tells you comands you can issue to
see the call stack you can usually see in IDEs that offer a GUI
debugger, or to inspect variables, etc etc.
I do not use interactive debuggers in any language. Too much work. I use
a lot of print statements.
hth, kt
--
"As long as algebra is taught in school,
there will be prayer in school." - Cokie Roberts
"Stand firm in your refusal to remain conscious during algebra."
- Fran Lebowitz
"I'm an algebra liar. I figure two good lies make a positive."
- Tim Allen
"Algebra is the metaphysics of arithmetic." - John Ray
http://www.theoryyalgebra.com/
On 13 Mar, 17:24, Ken Tilton <····@theoryyalgebra.com> wrote:
> I do not use interactive debuggers in any language. Too much work. I use
> a lot of print statements.
Ken,
I'm interested in your statement here. Is this because the tools
you've used are not up to the job or is it just that you can always
outperform the software?
I've worked with people who can do the latter but I've also worked
with tools that fit the former. What I've never worked out is, if you
give the super bright programmers the best possible tool, do they
become even more productive or can they still beat the software most
of the time.
My interest is of course to work out the priority of adding a
graphical debugger to ABLE.
Cheers, Phil
http://phil.nullable.eu/
···············@gmail.com wrote:
> On 13 Mar, 17:24, Ken Tilton <····@theoryyalgebra.com> wrote:
>
>
>>I do not use interactive debuggers in any language. Too much work. I use
>>a lot of print statements.
>
>
> Ken,
>
> I'm interested in your statement here. Is this because the tools
> you've used are not up to the job or is it just that you can always
> outperform the software?
It is that the print statement and resulting log is a different tool. In
fact, you just had a good idea for a commercial Lisp vendor: take
Kenny's TRC function (or one of the logging functions used by their
programmers--they all have them) and polish/publish it.
As for even the best interactive debuggers... ever watch a programmer
using a great debugger? step. step. setp. inspect. inspect. step. step.
inspect. step. step. step. inspect. sh*t. they stepped over wherever the
data was going bad. start again.
I run, quit look at /tons/ of information, all at once. All sorts of
understanding, new suspicions, new hypotheses arise. I see surprises in
variables I tossed in for the hell of it, which I might not take the
time to inspect manually. Rinse repeat. Some prints come out, some go
in. Useless prints removed, new ones based on new ideas inserted. No
step, no inspect, nothing interactive. Batch debugging. In tricky areas
the print statements stay, commented out until more trouble arises in
that corner of the system.
>
> I've worked with people who can do the latter but I've also worked
> with tools that fit the former. What I've never worked out is, if you
> give the super bright programmers the best possible tool, do they
> become even more productive or can they still beat the software most
> of the time.
I have used great interactive debuggers, fwiw.
>
> My interest is of course to work out the priority of adding a
> graphical debugger to ABLE.
One thing that skews my opinion is that I like to avoid work, so I try
to build generic engines, often ones searching some solution space for
an answer, or at least ones with less code relative to the functionality
covered. So if I set a break point, I might hit it a thousand times
before I get to the interesting one. yes, I have used debuggers with
conditional breaks, but again, most bugs are not a case of, gee this
ten-line function is miscomputing 42, they are more like, geez, x+x
transforms to x^2? with the annotation "combine signed numbers?" So I
have this huge AI engine that got into the scotch cabinet at some point,
and it could be over here in this module or over there in that module,
who knows, time for a shotgun blast of prints.
A lot of times I will be astonished to see that the program /first/ came
up with 2x, /then/ came up with x^2, but only because I have a big long
log and I see both results popping out. Debugging interactively I might
step up to and thru the correct calculation and then go off on a
tangent, or worse, with a conditional debugger I might stop only at the
bad calculation and not even be aware of the fact that it /did/ hit the
right result at one point.
etc etc.
kt
--
"As long as algebra is taught in school,
there will be prayer in school." - Cokie Roberts
"Stand firm in your refusal to remain conscious during algebra."
- Fran Lebowitz
"I'm an algebra liar. I figure two good lies make a positive."
- Tim Allen
"Algebra is the metaphysics of arithmetic." - John Ray
http://www.theoryyalgebra.com/
Ken Tilton <···@theoryyalgebra.com> writes:
> ···············@gmail.com wrote:
>> On 13 Mar, 17:24, Ken Tilton <····@theoryyalgebra.com> wrote:
>>
>>
>>>I do not use interactive debuggers in any language. Too much work. I use
>>>a lot of print statements.
I concur, print statements are better than stepping. You never know if
you should step over to spare insignificant details, or step into to
encounter the bug...
>> My interest is of course to work out the priority of adding a
>> graphical debugger to ABLE.
>
> One thing that skews my opinion is that I like to avoid work, so I try
> to build generic engines, often ones searching some solution space for
> an answer, or at least ones with less code relative to the
> functionality covered. So if I set a break point, I might hit it a
> thousand times before I get to the interesting one. yes, I have used
> debuggers with conditional breaks, but again, most bugs are not a case
> of, gee this ten-line function is miscomputing 42, they are more like,
> geez, x+x transforms to x^2? with the annotation "combine signed
> numbers?" So I have this huge AI engine that got into the scotch
> cabinet at some point, and it could be over here in this module or
> over there in that module, who knows, time for a shotgun blast of
> prints.
>
> A lot of times I will be astonished to see that the program /first/
> came up with 2x, /then/ came up with x^2, but only because I have a
> big long log and I see both results popping out. Debugging
> interactively I might step up to and thru the correct calculation and
> then go off on a tangent, or worse, with a conditional debugger I
> might stop only at the bad calculation and not even be aware of the
> fact that it /did/ hit the right result at one point.
Anybody interested in debugging should watch google's video "Debugging
Backward in Time".
http://video.google.com/videoplay?docid=3897010229726822034&q=debugger
PRINT _expressions_ and TRACE are basically a crude way to do that.
Note that PRINT aren't statements, but expressions! The nice thing is
that you can put any subexpression in a PRINT:
(defun f (x) (if (< (PRINT x) 0) x (* x (f (1- x)))))
--
__Pascal Bourguignon__
http://www.informatimago.com
http://pjb.ogamita.org
On 14 Mar, 00:40, Ken Tilton <····@theoryyalgebra.com> wrote:
> ···············@gmail.com wrote:
> > On 13 Mar, 17:24, Ken Tilton <····@theoryyalgebra.com> wrote:
> and it could be over here in this module or over there in that module,
> who knows, time for a shotgun blast of prints.
I once left a debugging print statement in an application that went
live. It was only slightly offensive but I learnt that derivatives
traders don't share our sense of humor. Oh well...
Phil
···············@gmail.com wrote:
> On 14 Mar, 00:40, Ken Tilton <····@theoryyalgebra.com> wrote:
>
>>···············@gmail.com wrote:
>>
>>>On 13 Mar, 17:24, Ken Tilton <····@theoryyalgebra.com> wrote:
>
>
>>and it could be over here in this module or over there in that module,
>>who knows, time for a shotgun blast of prints.
>
>
> I once left a debugging print statement in an application that went
> live. It was only slightly offensive but I learnt that derivatives
> traders don't share our sense of humor. Oh well...
I once had a programmer embed an application state change in a debugging
print. When I had to work on his code and commented out the print, spent
a while working that one out... you think I am tough on youse guys? If I
had known about tfb the elders soap vat...
kt
--
"As long as algebra is taught in school,
there will be prayer in school." - Cokie Roberts
"Stand firm in your refusal to remain conscious during algebra."
- Fran Lebowitz
"I'm an algebra liar. I figure two good lies make a positive."
- Tim Allen
"Algebra is the metaphysics of arithmetic." - John Ray
http://www.theoryyalgebra.com/
Ken Tilton <···@theoryyalgebra.com> writes:
> I run, quit look at /tons/ of information, all at once. All sorts of
> understanding, new suspicions, new hypotheses arise.
A related technique, that I've found myself inadvertently using,
particularly when debugging multithreaded code (where the print
statements include timestamps and thread ids along with values of
interest), is that once I've added enough print statements to have
reams and reams of data with which to distract my conscious mind, my
subconscious mind is finally left alone and figures out what the bug
is in a flash of insight.
-Peter
Peter Seibel wrote:
> Ken Tilton <···@theoryyalgebra.com> writes:
>
>
>>I run, quit look at /tons/ of information, all at once. All sorts of
>>understanding, new suspicions, new hypotheses arise.
>
>
> A related technique, that I've found myself inadvertently using,
> particularly when debugging multithreaded code (where the print
> statements include timestamps and thread ids along with values of
> interest), is that once I've added enough print statements to have
> reams and reams of data with which to distract my conscious mind, my
> subconscious mind is finally left alone and figures out what the bug
> is in a flash of insight.
A well-known phenomenon is the easy fix after a good night's sleep.
Unlike the spotted head woodpecker (or is that the beer? anyway...) down
in that Mississippi (Alabama?) swamp, we did manage to catch one of
these incidents on tape. What happened was that I came in all rested and
relaxed, parked my coffee, rolled up my sleaves and whistling Dixie
typed in about twent print statements.
Turns out that when exhausted I haven't the strength to type in all
those print statements and insist on figuring it out. With my exhausted
brain. As my French teacher said, it is much easier to recognize a bit
of vocabulary than come up with it.
kt
ps. Welcome back, Peter. I told the chimps you were back, they went...
nahh, too easy. k
--
"As long as algebra is taught in school,
there will be prayer in school." - Cokie Roberts
"Stand firm in your refusal to remain conscious during algebra."
- Fran Lebowitz
"I'm an algebra liar. I figure two good lies make a positive."
- Tim Allen
"Algebra is the metaphysics of arithmetic." - John Ray
http://www.theoryyalgebra.com/
On 13 Mar 2007 10:45:59 -0700, ···············@gmail.com said:
| On 13 Mar, 17:24, Ken Tilton <····@theoryyalgebra.com> wrote:
|| I do not use interactive debuggers in any language. Too much work. I use
|| a lot of print statements.
| Ken,
| I'm interested in your statement here. Is this because the tools
| you've used are not up to the job or is it just that you can always
| outperform the software?
| I've worked with people who can do the latter but I've also worked
| with tools that fit the former. What I've never worked out is, if you
| give the super bright programmers the best possible tool, do they
| become even more productive or can they still beat the software most
| of the time.
In my own personal opinion, which is mine only, there are two
typical cases of using a debugger (apart from some number of
atypical cases about which it is difficult to generalize):
(1) examine program state at the point the debugger was
entered (backtrace, local variables, available restarts,
etc.)---that is useful and helps productivity;
(2) stepping through code---I've always felt that to be rather
unproductive, and much prefer to try to understand the
program source.
Also, for non-interactive debugging, TRACE is a good friend as
is the practice of calling SIGNAL for non-error conditions and
establishing handlers for those during test/investigative runs.
All disclaimers about mileage apply...
---Vassil.
--
Definitely worth seeing: "Das Leben der Anderen" ("The Lives of Others").
In article <················@eskimo.com>,
Vassil Nikolov <···············@pobox.com> wrote:
> On 13 Mar 2007 10:45:59 -0700, ···············@gmail.com said:
>
> | On 13 Mar, 17:24, Ken Tilton <····@theoryyalgebra.com> wrote:
> || I do not use interactive debuggers in any language. Too much work. I use
> || a lot of print statements.
>
> | Ken,
>
> | I'm interested in your statement here. Is this because the tools
> | you've used are not up to the job or is it just that you can always
> | outperform the software?
>
> | I've worked with people who can do the latter but I've also worked
> | with tools that fit the former. What I've never worked out is, if you
> | give the super bright programmers the best possible tool, do they
> | become even more productive or can they still beat the software most
> | of the time.
>
> In my own personal opinion, which is mine only, there are two
> typical cases of using a debugger (apart from some number of
> atypical cases about which it is difficult to generalize):
>
> (1) examine program state at the point the debugger was
> entered (backtrace, local variables, available restarts,
> etc.)---that is useful and helps productivity;
EXAMINE is certainly one use case.
there are others:
* FIX and RESUME.
* FIX and RESTART.
* NAVIGATE source (with a source-level debugger or an attached editor).
* WRITE BUGREPORT.
* MONITOR locations.
* MANAGE traps and breakpoints (list, enable, disable, view, ...)
>
> (2) stepping through code---I've always felt that to be rather
> unproductive, and much prefer to try to understand the
> program source.
Most of the time this is provided by a separate STEP tool.
I'm using it sometimes. In the presence of a compiler
and compiled code it is of limited value. Stepping best
works with an Interpreter and interpreted code.
In compiled code, you might be able to step on
instruction level.
Sometimes the source makes only sense, when one
has representative data at hand (application data,
stack frames, ...) and you can try out things at the
debugger REPL. Especially if the source is only
remotely what gets executed, for example when you
use macros in the source. Then stepping through
Lisp code and seeing the expansions is one way
to debug this.
>
> Also, for non-interactive debugging, TRACE is a good friend as
> is the practice of calling SIGNAL for non-error conditions and
> establishing handlers for those during test/investigative runs.
>
> All disclaimers about mileage apply...
>
> ---Vassil.
--
http://lispm.dyndns.org
"csledge" <·········@yahoo.com> writes:
> Hi all,
> I am using the clisp interpretter avaliable with cygwin. I am
> new to the language. I would like to know how to use the debugger,
> everytime I make a mistake it takes me to the debugger I dont know how
> to proceed.
1- read the Implementation Notes on http://clisp.cons.org/
2- when you want some help, type something like ?, help, :help, etc...
(in the case of clisp debugger, it's ?)
3- here is an little example:
C/USER[11]> (defun f (x) (if (<= x 0) (/ x) (* (/ x) (f (1- x)))))
F
C/USER[12]> (f 5)
*** - division by zero ; oops we've got a bug!
The following restarts are available:
ABORT :R1 ABORT
C/Break 1 USER[13]> :bt
<1> #<SYSTEM-FUNCTION EXT:SHOW-STACK> 3 ; these are
<2> #<COMPILED-FUNCTION SYSTEM::PRINT-BACKTRACE> ; compiled
<3> #<COMPILED-FUNCTION SYSTEM::DEBUG-BACKTRACE> ; functions.
<4> #<SYSTEM-FUNCTION SYSTEM::READ-EVAL-PRINT> 2
<5> #<COMPILED-FUNCTION SYSTEM::BREAK-LOOP-2-2> ; not much
<6> #<SYSTEM-FUNCTION SYSTEM::SAME-ENV-AS> 2 ; debugging
<7> #<COMPILED-FUNCTION SYSTEM::BREAK-LOOP-2> ; can be done
<8> #<SYSTEM-FUNCTION SYSTEM::DRIVER> ; on then.
<9> #<COMPILED-FUNCTION SYSTEM::BREAK-LOOP>
<10> #<SYSTEM-FUNCTION INVOKE-DEBUGGER> 1
<11> #<SYSTEM-FUNCTION /> 1
<12> #<SPECIAL-OPERATOR IF>
EVAL frame for form (IF (<= X 0) (/ X) (* (/ X) (F (1- X)))) ; for interpreted code it's easier.
APPLY frame for call (F '0)
<13> #<FUNCTION F (X) (DECLARE (SYSTEM::IN-DEFUN F)) (BLOCK F (IF (<= X 0) (/ X) (* (/ X) (F (1- X)))))> 1
EVAL frame for form (F (1- X))
EVAL frame for form (* (/ X) (F (1- X)))
<14> #<SPECIAL-OPERATOR IF>
EVAL frame for form (IF (<= X 0) (/ X) (* (/ X) (F (1- X))))
APPLY frame for call (F '1)
<15> #<FUNCTION F (X) (DECLARE (SYSTEM::IN-DEFUN F)) (BLOCK F (IF (<= X 0) (/ X) (* (/ X) (F (1- X)))))> 1
EVAL frame for form (F (1- X))
EVAL frame for form (* (/ X) (F (1- X)))
<16> #<SPECIAL-OPERATOR IF>
EVAL frame for form (IF (<= X 0) (/ X) (* (/ X) (F (1- X))))
APPLY frame for call (F '2)
<17> #<FUNCTION F (X) (DECLARE (SYSTEM::IN-DEFUN F)) (BLOCK F (IF (<= X 0) (/ X) (* (/ X) (F (1- X)))))> 1
EVAL frame for form (F (1- X))
EVAL frame for form (* (/ X) (F (1- X)))
<18> #<SPECIAL-OPERATOR IF>
EVAL frame for form (IF (<= X 0) (/ X) (* (/ X) (F (1- X))))
APPLY frame for call (F '3)
<19> #<FUNCTION F (X) (DECLARE (SYSTEM::IN-DEFUN F)) (BLOCK F (IF (<= X 0) (/ X) (* (/ X) (F (1- X)))))> 1
EVAL frame for form (F (1- X))
EVAL frame for form (* (/ X) (F (1- X)))
<20> #<SPECIAL-OPERATOR IF>
EVAL frame for form (IF (<= X 0) (/ X) (* (/ X) (F (1- X))))
APPLY frame for call (F '4)
<21> #<FUNCTION F (X) (DECLARE (SYSTEM::IN-DEFUN F)) (BLOCK F (IF (<= X 0) (/ X) (* (/ X) (F (1- X)))))> 1
EVAL frame for form (F (1- X))
EVAL frame for form (* (/ X) (F (1- X)))
<22> #<SPECIAL-OPERATOR IF>
EVAL frame for form (IF (<= X 0) (/ X) (* (/ X) (F (1- X))))
APPLY frame for call (F '5)
<23> #<FUNCTION F (X) (DECLARE (SYSTEM::IN-DEFUN F)) (BLOCK F (IF (<= X 0) (/ X) (* (/ X) (F (1- X)))))> 1
EVAL frame for form (F 5)
Printed 23 frames
C/Break 1 USER[13]> :u ; I move up to the next interpreted frame
<1> #<SPECIAL-OPERATOR IF>
EVAL frame for form (IF (<= X 0) (/ X) (* (/ X) (F (1- X))))
C/Break 1 USER[13]> x ; we can type any lisp expression, this is a REPL
0
C/Break 1 USER[13]> :u
APPLY frame for call (F '0)
C/Break 1 USER[13]> :u
EVAL frame for form (F (1- X))
C/Break 1 USER[13]> :u
EVAL frame for form (* (/ X) (F (1- X)))
C/Break 1 USER[13]> x ; they're evaluated in the lexical environment of the current frame
1
C/Break 1 USER[13]> :d
EVAL frame for form (F (1- X))
C/Break 1 USER[13]> :d
APPLY frame for call (F '0)
C/Break 1 USER[13]> :d
<1> #<SPECIAL-OPERATOR IF>
EVAL frame for form (IF (<= X 0) (/ X) (* (/ X) (F (1- X))))
C/Break 1 USER[13]> (<= x 0)
T
C/Break 1 USER[13]> ? ; let's assume I don't remember the command to return a value:
Commands may be abbreviated as shown in the second column.
COMMAND ABBR DESCRIPTION
Help :h, ? this command list
Error :e Print the last error message
Inspect :i Inspect the last error
Abort :a abort to the next recent input loop
Unwind :uw abort to the next recent input loop
Reset :re toggle *PACKAGE* and *READTABLE* between the
local bindings and the sane values
Quit :q quit to the top-level input loop
Mode-1 :m1 inspect all the stack elements
Mode-2 :m2 inspect all the frames
Mode-3 :m3 inspect only lexical frames
Mode-4 :m4 inspect only EVAL and APPLY frames (default)
Mode-5 :m5 inspect only APPLY frames
Where :w inspect this frame
Up :u go up one frame, inspect it
Top :t go to top frame, inspect it
Down :d go down one frame, inspect it
Bottom :b go to bottom (most recent) frame, inspect it
Backtrace-1 :bt1 list all stack elements
Backtrace-2 :bt2 list all frames
Backtrace-3 :bt3 list all lexical frames
Backtrace-4 :bt4 list all EVAL and APPLY frames
Backtrace-5 :bt5 list all APPLY frames
Backtrace :bt list stack in current mode
Backtrace-l :bl list stack in current mode.
Limit of frames to print will be prompted for.
Frame-limit :fl set the frame-limit. This many frames will
be printed in a backtrace at most.
Break+ :br+ set breakpoint in EVAL frame
Break- :br- disable breakpoint in EVAL frame
Redo :rd re-evaluate form in EVAL frame
Return :rt leave EVAL frame, prescribing the return values
The following restarts are available:
ABORT :R1 ABORT
C/Break 1 USER[13]> :rt ; it was :rt
Values: 1
1/120
C/USER[14]>
When you break into the debugger, you also have a list of "restarts".
In the example above, the only one was to ABORT (:r1). But there may
be some other restarts (retry, give a correct function or value,
reload, etc).
C/USER[14]> (defun f (x) (if (<= x 1) (// x) (* (/ x) (f (1- x)))))
F
C/USER[15]> (f 5) ; Assume it takes 2 hours to reach (f 1).
*** - EVAL: undefined function //
The following restarts are available:
USE-VALUE :R1 You may input a value to be used instead of (FDEFINITION '//).
RETRY :R2 Retry
STORE-VALUE :R3 You may input a new value for (FDEFINITION '//).
ABORT :R4 ABORT
C/Break 1 USER[16]> :r1
Use instead of (FDEFINITION '//): #.(function /) ; we must use #. to enter functions...
1/120
C/USER[17]>
--
__Pascal Bourguignon__
http://www.informatimago.com
http://pjb.ogamita.org