From: pTymN
Subject: C++ style debugging
Date: 
Message-ID: <1155220653.240028.40910@i42g2000cwa.googlegroups.com>
Hi all,

Is there a reason that trying to use breakpoints/watches/stepping is a
bad idea for Lisp? I've noticed a lack of these things, which has
forced me to keep functions nice and small like they probably should
be. However, 10 years of debugging the C++ way dies hard.

I would be interested to see how others who have come from the C++
background have adapted their debugging practices to Lisp.

-Tim Kerchmar

From: Bill Atkins
Subject: Re: C++ style debugging
Date: 
Message-ID: <1155223366.745231.159140@m79g2000cwm.googlegroups.com>
pTymN wrote:
> Hi all,
>
> Is there a reason that trying to use breakpoints/watches/stepping is a
> bad idea for Lisp?

I don't think these are a bad idea for Lisp.

>                          I've noticed a lack of these things, which has
> forced me to keep functions nice and small like they probably should
> be. However, 10 years of debugging the C++ way dies hard.
>
> I would be interested to see how others who have come from the C++
> background have adapted their debugging practices to Lisp.
>
> -Tim Kerchmar

Most Lisp environments support this kind of debugging.  LispWorks (and
I would imagine the other commercial environments as well) supports
breakpoints, watching, and stepping.  SLIME has support for watching.

The Common Lisp function BREAK is useful for these sorts of things.
You can pass BREAK a format string and arguments to get information
about what's happening inside a function even without an IDE.

(defun foo-bar (baz quux)
  (loop for x from 0 to baz
          do (break "considering ~D" x)
          collect (list x quux))))

Obviously you can pass no arguments and use this just to set
breakpoints.  BREAK signals a continuable error, so your environment
will normally give you a handy interface for picking restarts and
examining variable values and then continuing on (again, this is
normally possible only with interpreted code since compiled code no
longer has this information).

There is also the Common Lisp form STEP, which will let you
interactively step through a form (however, it doesn't let you step
into function calls - at least not as part of its standard behavior).

(step (let ((x 3)) (+ x (sqrt x) (/ 5 x))))

HTH,
Bill
From: ···············@yahoo.com
Subject: Re: C++ style debugging
Date: 
Message-ID: <1155224588.758037.144370@h48g2000cwc.googlegroups.com>
In addition to what Bill says, put

(declaim (optimize safety debug))

at the top of the file when you're debugging compiled code.  The
"debug" is like the -g flag to a C or Java compiler.  "Safety" tightens
up checking of, e.g., the number and types of arguments.

Allegro CL supports stepping through compiled code.

Your Lisp system will have documentation on stepping and on the
debugger.  There's always a learning curve for this kind of thing, but
it's well worth it.
From: Ken Tilton
Subject: Re: C++ style debugging
Date: 
Message-ID: <CKICg.3$G_1.0@newsfe12.lga>
pTymN wrote:
> Hi all,
> 
> Is there a reason that trying to use breakpoints/watches/stepping is a
> bad idea for Lisp? 

It might be because it is harder to do in a dynamic language, but what 
do I know? The compiler types will have better answers.

> I've noticed a lack of these things, which has
> forced me to keep functions nice and small like they probably should
> be. However, 10 years of debugging the C++ way dies hard.
> 
> I would be interested to see how others who have come from the C++
> background have adapted their debugging practices to Lisp.

I actually do not step through code even when a point and click IDE 
makes it possible. I always create a more or less elaborate logging 
mechanism, run the thing till it misbehaves, check the log. With the 
insanely fast turnaround --- well, I take that back. One step in my road 
to lisp was seeing Think C (by then Symantec) loce incremental linking, 
so if I had to add a few print statements to get more info I was always 
looking at a thirty-forty second hit between iterations.

But with Lisp that is not a problem. Even better, it is trivial to run 
just one problematic function (if it comes to that) and debug that.

Hmm, i should add that, currently, I am doing a lot of 
breaking/examining... but I do this with embedded code, again, my own 
little homebrew debugging tools. These embeddings can be left in place 
but disabled where I know that I will be coming this way again on the 
next problem in a day or two, then quickly reenabled in all their 
complexity as soon as I have another problem.

So I do not know if steppers are hard or if no one is asking for them or 
both.

kt

-- 
Cells: http://common-lisp.net/project/cells/

"I'll say I'm losing my grip, and it feels terrific."
    -- Smiling husband to scowling wife, New Yorker cartoon
From: Paolo Amoroso
Subject: Re: C++ style debugging
Date: 
Message-ID: <87odusy5s9.fsf@plato.moon.paoloamoroso.it>
"pTymN" <·········@gmail.com> writes:

> Is there a reason that trying to use breakpoints/watches/stepping is a
> bad idea for Lisp? I've noticed a lack of these things, which has

What about BREAK and STEP?


Paolo
-- 
Why Lisp? http://wiki.alu.org/RtL%20Highlight%20Film
The Common Lisp Directory: http://www.cl-user.net
From: bradb
Subject: Re: C++ style debugging
Date: 
Message-ID: <1155225492.311093.54670@m79g2000cwm.googlegroups.com>
Paolo Amoroso wrote:
> "pTymN" <·········@gmail.com> writes:
>
> > Is there a reason that trying to use breakpoints/watches/stepping is a
> > bad idea for Lisp? I've noticed a lack of these things, which has
>
> What about BREAK and STEP?
>
>
> Paolo
> --
> Why Lisp? http://wiki.alu.org/RtL%20Highlight%20Film
> The Common Lisp Directory: http://www.cl-user.net

How do you break at a certain point and then single step?  It appears
that Slime supports single stepping, but only a couple of backends
actually support it.

Cheers
Brad
From: Alex Mizrahi
Subject: Re: C++ style debugging
Date: 
Message-ID: <44de20f8$0$15787$14726298@news.sunsite.dk>
(message (Hello 'pTymN)
(you :wrote  :on '(10 Aug 2006 07:37:33 -0700))
(

 p> Is there a reason that trying to use breakpoints/watches/stepping is a
 p> bad idea for Lisp?

it's a bad idea for C/C++ too, afaik Kernighan and Pike adviced to use trace 
log for debugging, making breakpoints/watches/stepping last resort. you 
might need this if you do some low-level stuff, if you have low-level bugs, 
or mess with third-party libraries -- for Lisp typically you don't have such 
problems.

)
(With-best-regards '(Alex Mizrahi) :aka 'killer_storm)
"People who lust for the Feel of keys on their fingertips (c) Inity") 
From: pTymN
Subject: Re: C++ style debugging
Date: 
Message-ID: <1155594198.939193.116210@75g2000cwc.googlegroups.com>
Alex Mizrahi wrote:
> (message (Hello 'pTymN)
> (you :wrote  :on '(10 Aug 2006 07:37:33 -0700))
> (
>
>  p> Is there a reason that trying to use breakpoints/watches/stepping is a
>  p> bad idea for Lisp?
>
> it's a bad idea for C/C++ too, afaik Kernighan and Pike adviced to use trace
> log for debugging, making breakpoints/watches/stepping last resort. you
> might need this if you do some low-level stuff, if you have low-level bugs,
> or mess with third-party libraries -- for Lisp typically you don't have such
> problems.
>
> )
> (With-best-regards '(Alex Mizrahi) :aka 'killer_storm)
> "People who lust for the Feel of keys on their fingertips (c) Inity")

I'm pretty used to logging stuff anyway, because the Visual Studio C++
command window and watch windows are retarted when it comes to
overloaded operators, which virtually any std:: based application has.
That said, I think that I'll try implementing some debugging macros,
because I'm very tired of (format t "DOT-PRODUCT = ~S~%" dot-product)
every time I want to check values. One other nice thought would be to
write a reader macro that allows me to insert a log entry with a stack
trace and new value anytime a particular symbol's value is changed.
From: Johan Ur Riise
Subject: Re: C++ style debugging
Date: 
Message-ID: <873bbryr4b.fsf@morr.riise-data.net>
"pTymN" <·········@gmail.com> writes:

> Alex Mizrahi wrote:

> That said, I think that I'll try implementing some debugging macros,
> because I'm very tired of (format t "DOT-PRODUCT = ~S~%" dot-product)
> every time I want to check values.

I like this one. Could also be called EXHIBIT (from COBOL).

CL-USER> (defmacro display (&rest symbols)
  (let ((format-statements 
          (loop 
             for sym in symbols
             collect `(format t  "~a: ~s~%" ',sym ,sym))))
    `(progn ,@format-statements)))
DISPLAY
CL-USER> (let ((a 2) (b 4))
  (let ((c (+ a b)))
    (display a b c *package* MOST-POSITIVE-FIXNUM)
    c))
A: 2
B: 4
C: 6
*PACKAGE*: #<PACKAGE COMMON-LISP-USER>
MOST-POSITIVE-FIXNUM: 281474976710655

6
CL-USER> 
From: Rob Warnock
Subject: Re: C++ style debugging
Date: 
Message-ID: <EZOdnQOKJIJnCHTZnZ2dnUVZ_s2dnZ2d@speakeasy.net>
Johan Ur Riise  <·····@riise-data.no> wrote:
+---------------
| "pTymN" <·········@gmail.com> writes:
| > Alex Mizrahi wrote:
| > ...very tired of (format t "DOT-PRODUCT = ~S~%" dot-product)
| > every time I want to check values.
| 
| I like this one. Could also be called EXHIBIT (from COBOL).
| 
| CL-USER> (defmacro display (&rest symbols)
|   (let ((format-statements 
|           (loop 
|              for sym in symbols
|              collect `(format t  "~a: ~s~%" ',sym ,sym))))
|     `(progn ,@format-statements)))
+---------------

Heh! A recurring pattern, it seems!  ;-}  I have two almost identical
macros, but which also take an optional "where am I?" parameter:

    ;;; A sometimes-helpful macro for debugging.
    (defmacro dbgv ((&optional (where "Unknown Location")) &rest forms)
      `(progn
	 (format t "~&DBGV: @~a:~%" ',where)
	 ,@(loop for form in forms collect
	   `(format t "~a = ~s~%" ',form ,form))))
				    
    ;;; HTML version of DBGV.
    (defmacro dbgvht ((&optional (where "Unknown Location")) &rest forms)
      `(progn
	 (format t "~&<br>DBGV: At ~a<br>~%" ',where)
	 ,@(loop for form in forms collect
	   `(format t "&nbsp;&nbsp;&nbsp;~a = ~s<br>~%" ',form ,form))))

DBGV stands for "DeBuG Values", and DBGVHT (should it have been called
"DBGV/HT"?) is the same, but for use when debugging dynamic web pages.

+---------------
| DISPLAY
| CL-USER> (let ((a 2) (b 4))
|   (let ((c (+ a b)))
|     (display a b c *package* MOST-POSITIVE-FIXNUM)
|     c))
| A: 2
| B: 4
| C: 6
| *PACKAGE*: #<PACKAGE COMMON-LISP-USER>
| MOST-POSITIVE-FIXNUM: 281474976710655
| 
| 6
| CL-USER> 
+---------------

    > (let ((a 2) (b 4))
        (let ((c (+ a b)))
          (dbgv (nested-let) a b c *package* most-positive-fixnum)
          c))
    DBGV: @NESTED-LET:
    A = 2
    B = 4
    C = 6
    *PACKAGE* = #<The COMMON-LISP-USER package, 114/192 internal, 0/9 external>
    MOST-POSITIVE-FIXNUM = 536870911
    6
    > 
    > (let ((a 2) (b 4))
        (let ((c (+ a b)))
          (dbgvht (nested-let-in-a-web-page)
	    a b c *package* most-positive-fixnum)
          c))
    <br>DBGV: At NESTED-LET-IN-A-WEB-PAGE<br>
    &nbsp;&nbsp;&nbsp;A = 2<br>
    &nbsp;&nbsp;&nbsp;B = 4<br>
    &nbsp;&nbsp;&nbsp;C = 6<br>
    &nbsp;&nbsp;&nbsp;*PACKAGE* = #<The COMMON-LISP-USER package, 115/192 internal, 0/9 external><br>
    &nbsp;&nbsp;&nbsp;MOST-POSITIVE-FIXNUM = 536870911<br>
    6
    > 

But note that even with your version the "SYMBOLS" don't actually
have to be just symbols -- arbitrary forms work just fine, too:

    > (let ((a 2) (b 4))
        (let ((c (+ a b)))
          (dbgv ()
	    a b c
	    (+ a b)
	    (eql c (+ a b)))))
    DBGV: @Unknown Location:
    A = 2
    B = 4
    C = 6
    (+ A B) = 6
    (EQL C (+ A B)) = T
    NIL
    > 

Sometimes I find that useful.


-Rob

p.s. Hmmm... Now that I know FORMAT a bit better than when I first
wrote DBGV, maybe it should be defined this way:  ;-}  ;-}

    (defmacro dbgv ((&optional (where "Unknown Location")) &rest forms)
      `(format t "~&DBGV: @~a:~%~:{~a = ~s~%~}"
		 ',where
	         (list ,@(loop for form in forms collect
		          `(list ',form ,form)))))

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Johan Ur Riise
Subject: Re: C++ style debugging
Date: 
Message-ID: <8764g6xlzn.fsf@morr.riise-data.net>
····@rpw3.org (Rob Warnock) writes:

>     ;;; HTML version of DBGV.
>     (defmacro dbgvht ((&optional (where "Unknown Location")) &rest forms)
>       `(progn
> 	 (format t "~&<br>DBGV: At ~a<br>~%" ',where)
> 	 ,@(loop for form in forms collect
> 	   `(format t "&nbsp;&nbsp;&nbsp;~a = ~s<br>~%" ',form ,form))))

This is a great idea. The debug-info right onto the web-page. noted.