From: ·················@gmail.com
Subject: A simple debugging macro
Date: 
Message-ID: <23a2fa9f-68ea-48f4-939a-a4bc040516c2@s12g2000prg.googlegroups.com>
Hello all,

I wrote this simple macro a while back and I've found it to be
extremely useful for old-fashioned trace style debugging.  Maybe
others will find it useful as well.  Thoughts or criticism are
welcome.  Perhaps others have similar macros or other methods of doing
this that are better.

This is the macro:

(eval-when (:compile-toplevel :load-toplevel :execute)
  (defvar *debug* t)

  (defmacro print-vars (&rest vars)
    "Prints variables listed in vars to *trace-output*. The first
argument can be a string which will be printed directly."
    (when *debug*
      `(progn (format *trace-output* "TRACE: ")
         ,(when (stringp (first vars))
                     `(format *trace-output* "~A " ,(pop vars)))
              ,@(loop for var in vars
                   collect `(format *trace-output* "~A=~S "
',var ,var))
              (format *trace-output* "~%" )
              (finish-output *trace-output*)))))


This is how you use it:

CL-USER 46 > (let ((a 10))
                   (print-vars "before fib loop" a)
                   (loop for n from 1 to a
                         for x = 1 then y
                         and y = 1 then (+ x y)
                         do (print-vars n x y))
                   (print-vars "after fib loop" (* a a)))
TRACE: before fib loop A=10
TRACE: N=1 X=1 Y=1
TRACE: N=2 X=1 Y=2
TRACE: N=3 X=2 Y=3
TRACE: N=4 X=3 Y=5
TRACE: N=5 X=5 Y=8
TRACE: N=6 X=8 Y=13
TRACE: N=7 X=13 Y=21
TRACE: N=8 X=21 Y=34
TRACE: N=9 X=34 Y=55
TRACE: N=10 X=55 Y=89
TRACE: after fib loop (* A A)=100
NIL


Regards,

Anthony

From: Ken Tilton
Subject: Re: A simple debugging macro
Date: 
Message-ID: <X3O3j.137$Wr5.135@newsfe10.lga>
·················@gmail.com wrote:
> Hello all,
> 
> I wrote this simple macro a while back and I've found it to be
> extremely useful for old-fashioned trace style debugging.  Maybe
> others will find it useful as well.  Thoughts or criticism are
> welcome.  Perhaps others have similar macros or other methods of doing
> this that are better.

Think to come of it, that would be a way kewl project, Ye Ultimate Lisp 
Debuggery Tools. Yer hired.

You probably want a long form and a short form, feature richer vs typer 
friendlier.

In my long form (TRC) if the first arg is not a string then it is a form 
to be evaluated at run time to determine if that output should be emitted.

SOmeone suggested allowing strings in other positions, presumably 
someone who just adores using the shift key and finding the " key. Nah, 
just do this: if the arg is a keyword, just emit it, else emit the 
source followed by the value. Yes, hairy forms can make for copious 
output, but not so often so we'll live.

Aside: recently Duane divulged the secrets of knowing where I am in the 
ACL source at compile-time, sadly forgotten. You could allow callers to 
offer :wc for "where called" and auto-emit whatever the implementation 
offers.

Getting back to my short form, mine takes this:

    (trcx a b c)

...and expands that to the long form:

    (trc "a" :b b :c c)

I am meaning to add the utterly q&d:

    (trcxx yo-mama)

expanding to:

    (trc "yo-mamma" yo-mama)

Meanwhile, I think one massively necessary thing you must deliver is 
something like my eko and ekx:


    (eko ("hi there" a b) (super-form a b))

which calls the body and then before returning the result prints out the 
story of what result got returned along with the other stuff as if by 
TRC. ekx is the short form:

   (ekx yo-mama super-form a b)

Lisp is this awesome functional thangy, so without EK* I have to hack 
the code massively with a let form or progn to capture an intermediate 
result and dump it. Ewwww, as the kids would say.


Due Monday.

kzo

-- 
http://www.theoryyalgebra.com/

"In the morning, hear the Way;
  in the evening, die content!"
                     -- Confucius
From: Frank Goenninger DG1SBG
Subject: Re: A simple debugging macro
Date: 
Message-ID: <lzve7kf4yn.fsf@pcsde001.de.goenninger.net>
Ken Tilton <···········@optonline.net> writes:

> ·················@gmail.com wrote:
>> Hello all,
>>
>> I wrote this simple macro a while back and I've found it to be
>> extremely useful for old-fashioned trace style debugging.  Maybe
>> others will find it useful as well.  Thoughts or criticism are
>> welcome.  Perhaps others have similar macros or other methods of doing
>> this that are better.
>
> Think to come of it, that would be a way kewl project, Ye Ultimate
> Lisp Debuggery Tools. Yer hired.

Adding to the wish list:

* Being able to turn on debugging WITHOUT re-compiling everything (as
  Rainer already pointed out)

* Logging of debug output into a file or (on *nix/OS X) to syslog

I have some ideas for this, of course:

;;; -*- mode: Lisp; Syntax: Common-Lisp; Package: gt.app.dbg; -*-

(in-package :cl-user)
(pushnew :net.goenninger.app.debug *features*)

(defpackage #:net.goenninger.app.debug
  (:use
   #:common-lisp
	 #:utils-kt
 	 #:cells
   #:net.goenninger.app.tools)
  (:nicknames :gnc.app.dbg)
  (:export
        #:logmsg
        #:*module*
        #:in-module
        #:enable-debugging
        #:disable-debugging
        #:reset-debugging-settings
	#:defdbgobs))

(in-package :net.goenninger.app.debug)

;;; ----------------------------------------------------------------------------
;;;    Debug Message Printing And Logging
;;; ----------------------------------------------------------------------------
;;; Requires: utils-kt package (by Kenneth Tilton)

(defun find-package-defining-symbol (designator)
  (let ((name (string designator)))
    (labels ((in-package-p (package)
	      (nth-value 1 (find-symbol name package))))
     (if (member (in-package-p *package*) '(:external :internal))
	 *package*
	 (find :external (package-use-list *package*) :key #'in-package-p)))))

(defparameter *debug-modules* nil "Holds the module names for which debugging is enabled globally.")

(defparameter *module* nil "Holds the currently active module name.")

(defparameter *debug-functions* nil "Holds the package and function names for which debugging is enabled.")

(defparameter *log-level* nil "Defines the log level above which messages are logged - one of [\":DEBUG\"|\":INFO\"|\":WARN\"|\":ERROR\"|\":CRITICAL\"|\":EMERGENCY\"].")

(defmacro in-module (module-name)
  (eval-when (:load-toplevel :compile-toplevel :execute)
    `(setf net.goenninger.app.debug:*module* (up$ ,module-name))))

(defmacro logmsg (msg-class method method-desc msg &rest msg-args)
  `(logmsg-fn ,msg-class
              (find-package-defining-symbol ,method)
              ,method
              ,method-desc
              ,msg
              ,@msg-args))

(defun logmsg-fn (msg-class package method method-desc msg &rest msg-args)
  (when (and (member (up$ (symbol-name method))
                     *debug-functions* :test #'string=)
             (member *module* *debug-modules* :test #'string=))
    (format *debug-io* "~&~%--- ~a --------------------------------------------------"
            (format-iso8601-time (get-universal-time) t))
    (format *debug-io* "~&*** ~A [ FN ~S ( ~A ) ]~&"
	          msg-class method method-desc)
    (format *debug-io* "*** ")
    (apply 'format *debug-io* msg msg-args)
    (format *debug-io* "~%")
    (force-output *debug-io*)))

(defmethod enable-debugging ((key (eql :module)) module-name)
  (pushnew (up$ module-name) *debug-modules* :test #'string=))

(defmethod enable-debugging ((key (eql :function)) function-name)
  (pushnew (up$ (symbol-name function-name)) *debug-functions* :test #'string=))

(defmethod disable-debugging ((key (eql :module)) module-name)
  (setf *debug-modules* (remove (up$ module-name) *debug-modules*
                                :test #'string=)))

(defmethod disable-debugging ((key (eql :function)) function-name)
  (setf *debug-modules* (remove (up$ (symbol-name function-name))
                                *debug-functions* :test #'string=)))

(defun reset-debugging-settings ()
  (setf *debug-modules* nil)
  (setf *debug-functions* nil))

;;; ----------------------------------------------------------------------------
;;; defdbgobs - Define standard debugging observer for a cell slot        MACRO
;;; ----------------------------------------------------------------------------
;;; slot-name   := Identifies the slot name to be observed
;;; class-desc  := Identifies the class, example: ((self my-class))
;;; 
;;; Requires: Cells 3.0 (by Kenneth Tilton)

(defmacro defdbgobs (slot-name class-desc)
  `(defobserver ,slot-name ,class-desc
     (logmsg :INFO 'observer ',slot-name
	     "~A of ~S: ~S -> ~S"
	     ',slot-name self old-value new-value )))

Just some thoughts ... ;-)

// frgo

-- 

  Frank Goenninger

  frgo(at)mac(dot)com

  "Don't ask me! I haven't been reading comp.lang.lisp long enough to 
  really know ..."
From: Edi Weitz
Subject: Re: A simple debugging macro
Date: 
Message-ID: <u3auo83uh.fsf@agharta.de>
On Fri, 30 Nov 2007 10:38:40 +0100, Frank Goenninger DG1SBG <·············@nomail.org> wrote:

>   frgo(at)mac(dot)com

BTW: frgo?  That's pretty close to frog, isn't it?  Frank, what are
you up to?

Edi.

-- 

Lisp is not dead, it just smells funny.

Real email: (replace (subseq ·········@agharta.de" 5) "edi")
From: Frank Goenninger DG1SBG
Subject: OT: "frgo" is not frog! WAS:  Re: A simple debugging macro
Date: 
Message-ID: <lzr6i8ezfw.fsf_-_@pcsde001.de.goenninger.net>
Edi Weitz <········@agharta.de> writes:

> On Fri, 30 Nov 2007 10:38:40 +0100, Frank Goenninger DG1SBG <·············@nomail.org> wrote:
>
>>   frgo(at)mac(dot)com
>
> BTW: frgo?  That's pretty close to frog, isn't it?  Frank, what are
> you up to?
>
> Edi.

Hi Edi!

You know, "frgo" is just an abbreviation of my name (2 letters first
name, 2 letters last name - obvious ;-) and has been my login on all 
my work and private computers now for more than 20 years. Also, if 
you could see my shirt now, there's that "frgo" also stiched in as 
a monogram.

I almost dropped that habit because of our Frog friend here - but I
then realized it would mean surrender if I actually do so. I was here
before Mr Froggy and I will be here after him. 

No, I don't want to be "connected" / associated with Flying Hybris
Frog "Consultancy" ... Glad you gave me the opportunity to point that
out - heh heh.

;-)

Frank

-- 

  Frank Goenninger

  frgo(at)mac(dot)com

  "Don't ask me! I haven't been reading comp.lang.lisp long enough to 
  really know ..."
From: Rainer Joswig
Subject: Re: OT: "frgo" is not frog! WAS:  Re: A simple debugging macro
Date: 
Message-ID: <joswig-5BAB28.15314530112007@news-europe.giganews.com>
In article <·················@pcsde001.de.goenninger.net>,
 Frank Goenninger DG1SBG <·············@nomail.org> wrote:

> Edi Weitz <········@agharta.de> writes:
> 
> > On Fri, 30 Nov 2007 10:38:40 +0100, Frank Goenninger DG1SBG <·············@nomail.org> wrote:
> >
> >>   frgo(at)mac(dot)com
> >
> > BTW: frgo?  That's pretty close to frog, isn't it?  Frank, what are
> > you up to?
> >
> > Edi.
> 
> Hi Edi!
> 
> You know, "frgo" is just an abbreviation of my name (2 letters first
> name, 2 letters last name - obvious ;-) and has been my login on all 
> my work and private computers now for more than 20 years. Also, if 
> you could see my shirt now, there's that "frgo" also stiched in as 
> a monogram.
> 
> I almost dropped that habit because of our Frog friend here - but I
> then realized it would mean surrender if I actually do so. I was here
> before Mr Froggy and I will be here after him. 
> 
> No, I don't want to be "connected" / associated with Flying Hybris
> Frog "Consultancy" ... Glad you gave me the opportunity to point that
> out - heh heh.
> 
> ;-)
> 
> Frank

But there is a certain attraction to frogs in the Lisp community.

See this:   http://www.frogsonice.com/

Even this:  http://www.frogsonice.com/froggy/

and then this:  http://www.frogsonice.com/work.html

She was assistant editor of the ANSI Common Lisp specification. Even hacking on Haskell.


Strange?

But true.
From: Ken Tilton
Subject: Re: OT: "frgo" is not frog! WAS:  Re: A simple debugging macro
Date: 
Message-ID: <MnW3j.10$jV3.1@newsfe09.lga>
Rainer Joswig wrote:
> In article <·················@pcsde001.de.goenninger.net>,
>  Frank Goenninger DG1SBG <·············@nomail.org> wrote:
> 
> 
>>Edi Weitz <········@agharta.de> writes:
>>
>>
>>>On Fri, 30 Nov 2007 10:38:40 +0100, Frank Goenninger DG1SBG <·············@nomail.org> wrote:
>>>
>>>
>>>>  frgo(at)mac(dot)com
>>>
>>>BTW: frgo?  That's pretty close to frog, isn't it?  Frank, what are
>>>you up to?

"Are you now, or have you ever been, a member of a pond?"?

kzo


-- 
http://www.theoryyalgebra.com/

"In the morning, hear the Way;
  in the evening, die content!"
                     -- Confucius
From: Frank Goenninger DG1SBG
Subject: Re: OT: "frgo" is not frog! WAS:  Re: A simple debugging macro
Date: 
Message-ID: <lzir3jy5rq.fsf@de.goenninger.net>
Ken Tilton <···········@optonline.net> writes:

> Rainer Joswig wrote:
>> In article <·················@pcsde001.de.goenninger.net>,
>>  Frank Goenninger DG1SBG <·············@nomail.org> wrote:
>>
>>
>>>Edi Weitz <········@agharta.de> writes:
>>>
>>>
>>>>On Fri, 30 Nov 2007 10:38:40 +0100, Frank Goenninger DG1SBG <·············@nomail.org> wrote:
>>>>
>>>>
>>>>>  frgo(at)mac(dot)com
>>>>
>>>>BTW: frgo?  That's pretty close to frog, isn't it?  Frank, what are
>>>>you up to?
>
> "Are you now, or have you ever been, a member of a pond?"?
>
> kzo

Huh? Ok - non-native English speaker here. It sounds familiar but
doesn't ring the bell loud enough for me to Get It.

Literal answer: The Flying Frogs are from another pond. Actually,
there's no pond here except Lake Constance (about 150 km to get there
- a good 1 hour drive on that German Autobahn A81 going straight from
Stuttgart) and, when looking from the US, I am over that little pond
called Atlantic Ocean. Even when looking from the High North
(everything North of the river Donau is just a sketch from the North
Pole for us here in South Germany) - here meaning from UK where our
friend JDH The Frog is located - there's that same Atlantic Ocean
between his area and my area. 

As all of you know I am running another company that, strangely, also
has some biological cross reference (but that is not intended). Google
is your friend if you want to know the details ;-)

Or what was it you were up to? ;-)))

Frank
From: Edi Weitz
Subject: Re: OT: "frgo" is not frog! WAS:  Re: A simple debugging macro
Date: 
Message-ID: <uzlwvo9qm.fsf@agharta.de>
On Fri, 30 Nov 2007 18:58:33 +0100, Frank Goenninger DG1SBG <·············@nomail.org> wrote:

>> "Are you now, or have you ever been, a member of a pond?"?
>
> Huh? Ok - non-native English speaker here. It sounds familiar but
> doesn't ring the bell loud enough for me to Get It.

  http://globalia.net/donlope/fz/lyrics/The_Yellow_Shark.html#Welcome

From another Frank... :)

Edi.

-- 

Lisp is not dead, it just smells funny.

Real email: (replace (subseq ·········@agharta.de" 5) "edi")
From: Ken Tilton
Subject: Re: OT: "frgo" is not frog! WAS:  Re: A simple debugging macro
Date: 
Message-ID: <Dk%3j.84$Ek2.5@newsfe08.lga>
Edi Weitz wrote:
> On Fri, 30 Nov 2007 18:58:33 +0100, Frank Goenninger DG1SBG <·············@nomail.org> wrote:
> 
> 
>>>"Are you now, or have you ever been, a member of a pond?"?
>>
>>Huh? Ok - non-native English speaker here.

In this case you need to have studied the US as a second history, not 
English as a second language.

>> It sounds familiar but
>>doesn't ring the bell loud enough for me to Get It.
> 
> 
>   http://globalia.net/donlope/fz/lyrics/The_Yellow_Shark.html#Welcome
> 
> From another Frank... :)

At long last, have you left no sense of US history?

    http://en.wikipedia.org/wiki/Joseph_McCarthy

You were pretty close, tho.

kt


-- 
http://www.theoryyalgebra.com/

"In the morning, hear the Way;
  in the evening, die content!"
                     -- Confucius
From: Albert Krewinkel
Subject: Re: OT: "frgo" is not frog! WAS:  Re: A simple debugging macro
Date: 
Message-ID: <fwusl2mirr8.fsf@pc06.inb.uni-luebeck.de>
Rainer Joswig <······@lisp.de> writes:
> But there is a certain attraction to frogs in the Lisp community.
>
> See this:   http://www.frogsonice.com/
>
> Even this:  http://www.frogsonice.com/froggy/
>
> and then this:  http://www.frogsonice.com/work.html
>
> She was assistant editor of the ANSI Common Lisp specification. Even hacking on Haskell.
>
>
> Strange?
>
> But true.

See also lush: http://lush.sf.net

-- 
Albert Krewinkel
From: Rainer Joswig
Subject: Re: A simple debugging macro
Date: 
Message-ID: <joswig-75739E.05315930112007@news-europe.giganews.com>
In article 
<····································@s12g2000prg.googlegroups.com>,
 ··················@gmail.com" <·················@gmail.com> wrote:

> Hello all,
> 
> I wrote this simple macro a while back and I've found it to be
> extremely useful for old-fashioned trace style debugging.  Maybe
> others will find it useful as well.  Thoughts or criticism are
> welcome.  Perhaps others have similar macros or other methods of doing
> this that are better.
> 
> This is the macro:
> 
> (eval-when (:compile-toplevel :load-toplevel :execute)
>   (defvar *debug* t)
> 
>   (defmacro print-vars (&rest vars)
>     "Prints variables listed in vars to *trace-output*. The first
> argument can be a string which will be printed directly."
>     (when *debug*

You have to recompile client code to switch tracing on or off.

>       `(progn (format *trace-output* "TRACE: ")
>          ,(when (stringp (first vars))

Why just the first arg? Allow strings in all positions.

>                      `(format *trace-output* "~A " ,(pop vars)))

FORMAT obsession. Inserting a string in a string and printing that.

>               ,@(loop for var in vars
>                    collect `(format *trace-output* "~A=~S "
> ',var ,var))
>               (format *trace-output* "~%" )

FORMAT obsession. TERPRI.

>               (finish-output *trace-output*)))))
> 
> 
> This is how you use it:
> 
> CL-USER 46 > (let ((a 10))
>                    (print-vars "before fib loop" a)
>                    (loop for n from 1 to a
>                          for x = 1 then y
>                          and y = 1 then (+ x y)
>                          do (print-vars n x y))
>                    (print-vars "after fib loop" (* a a)))
> TRACE: before fib loop A=10
> TRACE: N=1 X=1 Y=1
> TRACE: N=2 X=1 Y=2
> TRACE: N=3 X=2 Y=3
> TRACE: N=4 X=3 Y=5
> TRACE: N=5 X=5 Y=8
> TRACE: N=6 X=8 Y=13
> TRACE: N=7 X=13 Y=21
> TRACE: N=8 X=21 Y=34
> TRACE: N=9 X=34 Y=55
> TRACE: N=10 X=55 Y=89
> TRACE: after fib loop (* A A)=100
> NIL
> 
> 
> Regards,
> 
> Anthony

-- 
http://lispm.dyndns.org/
From: ·················@gmail.com
Subject: Re: A simple debugging macro
Date: 
Message-ID: <c343bcf2-1dd9-469d-98ef-060f00a406e3@d27g2000prf.googlegroups.com>
On Nov 29, 8:31 pm, Rainer Joswig <······@lisp.de> wrote:
> In article
> <····································@s12g2000prg.googlegroups.com>,
>
>
>
>  ··················@gmail.com" <·················@gmail.com> wrote:
> > Hello all,
>
> > I wrote this simple macro a while back and I've found it to be
> > extremely useful for old-fashioned trace style debugging.  Maybe
> > others will find it useful as well.  Thoughts or criticism are
> > welcome.  Perhaps others have similar macros or other methods of doing
> > this that are better.
>
> > This is the macro:
>
> > (eval-when (:compile-toplevel :load-toplevel :execute)
> >   (defvar *debug* t)
>
> >   (defmacro print-vars (&rest vars)
> >     "Prints variables listed in vars to *trace-output*. The first
> > argument can be a string which will be printed directly."
> >     (when *debug*
>
> You have to recompile client code to switch tracing on or off.
>

That was the intent of the macro, to allow the user to completely
compile-out the trace statements while leaving them in the code (thus
requiring a recompile of everything).  I actually don't use this
feature, so I'll take it out.  I usually just remove the PRINT-VARS
after I'm done debugging.

> >       `(progn (format *trace-output* "TRACE: ")
> >          ,(when (stringp (first vars))
>
> Why just the first arg? Allow strings in all positions.
>

This is a very good suggestion, I'll change the macro to handle it.


> >                      `(format *trace-output* "~A " ,(pop vars)))
>
> FORMAT obsession. Inserting a string in a string and printing that.
>

Good point.  I use used FORMAT because I was printing the string
followed by a space.  Perhaps I should use WRITE-STRING followed by
PRINC?

> >               ,@(loop for var in vars
> >                    collect `(format *trace-output* "~A=~S "
> > ',var ,var))
> >               (format *trace-output* "~%" )
>
> FORMAT obsession. TERPRI.
>
>

Excellent, this is exactly what I was looking for, good criticism.  My
inexperience is showing ;-)

Thanks for your input.  I'll rewrite it and post an update


>
> >               (finish-output *trace-output*)))))
>
> > This is how you use it:
>
> > CL-USER 46 > (let ((a 10))
> >                    (print-vars "before fib loop" a)
> >                    (loop for n from 1 to a
> >                          for x = 1 then y
> >                          and y = 1 then (+ x y)
> >                          do (print-vars n x y))
> >                    (print-vars "after fib loop" (* a a)))
> > TRACE: before fib loop A=10
> > TRACE: N=1 X=1 Y=1
> > TRACE: N=2 X=1 Y=2
> > TRACE: N=3 X=2 Y=3
> > TRACE: N=4 X=3 Y=5
> > TRACE: N=5 X=5 Y=8
> > TRACE: N=6 X=8 Y=13
> > TRACE: N=7 X=13 Y=21
> > TRACE: N=8 X=21 Y=34
> > TRACE: N=9 X=34 Y=55
> > TRACE: N=10 X=55 Y=89
> > TRACE: after fib loop (* A A)=100
> > NIL
>
> > Regards,
>
> > Anthony
>
> --http://lispm.dyndns.org/
From: ·················@gmail.com
Subject: Re: A simple debugging macro
Date: 
Message-ID: <3902da1f-97f1-483c-8e67-537d3a698555@e10g2000prf.googlegroups.com>
On Nov 29, 8:52 pm, ··················@gmail.com"
<·················@gmail.com> wrote:
> On Nov 29, 8:31 pm, Rainer Joswig <······@lisp.de> wrote:
>
>
>
> > In article
> > <····································@s12g2000prg.googlegroups.com>,
>
> >  ··················@gmail.com" <·················@gmail.com> wrote:
> > > Hello all,
>
> > > I wrote this simple macro a while back and I've found it to be
> > > extremely useful for old-fashioned trace style debugging.  Maybe
> > > others will find it useful as well.  Thoughts or criticism are
> > > welcome.  Perhaps others have similar macros or other methods of doing
> > > this that are better.
>
> > > This is the macro:
>
> > > (eval-when (:compile-toplevel :load-toplevel :execute)
> > >   (defvar *debug* t)
>
> > >   (defmacro print-vars (&rest vars)
> > >     "Prints variables listed in vars to *trace-output*. The first
> > > argument can be a string which will be printed directly."
> > >     (when *debug*
>
> > You have to recompile client code to switch tracing on or off.
>
> That was the intent of the macro, to allow the user to completely
> compile-out the trace statements while leaving them in the code (thus
> requiring a recompile of everything).  I actually don't use this
> feature, so I'll take it out.  I usually just remove the PRINT-VARS
> after I'm done debugging.
>
> > >       `(progn (format *trace-output* "TRACE: ")
> > >          ,(when (stringp (first vars))
>
> > Why just the first arg? Allow strings in all positions.
>
> This is a very good suggestion, I'll change the macro to handle it.
>
> > >                      `(format *trace-output* "~A " ,(pop vars)))
>
> > FORMAT obsession. Inserting a string in a string and printing that.
>
> Good point.  I use used FORMAT because I was printing the string
> followed by a space.  Perhaps I should use WRITE-STRING followed by
> PRINC?
>
> > >               ,@(loop for var in vars
> > >                    collect `(format *trace-output* "~A=~S "
> > > ',var ,var))
> > >               (format *trace-output* "~%" )
>
> > FORMAT obsession. TERPRI.
>
> Excellent, this is exactly what I was looking for, good criticism.  My
> inexperience is showing ;-)
>
> Thanks for your input.  I'll rewrite it and post an update
>
>
>
> > >               (finish-output *trace-output*)))))
>
> > > This is how you use it:
>
> > > CL-USER 46 > (let ((a 10))
> > >                    (print-vars "before fib loop" a)
> > >                    (loop for n from 1 to a
> > >                          for x = 1 then y
> > >                          and y = 1 then (+ x y)
> > >                          do (print-vars n x y))
> > >                    (print-vars "after fib loop" (* a a)))
> > > TRACE: before fib loop A=10
> > > TRACE: N=1 X=1 Y=1
> > > TRACE: N=2 X=1 Y=2
> > > TRACE: N=3 X=2 Y=3
> > > TRACE: N=4 X=3 Y=5
> > > TRACE: N=5 X=5 Y=8
> > > TRACE: N=6 X=8 Y=13
> > > TRACE: N=7 X=13 Y=21
> > > TRACE: N=8 X=21 Y=34
> > > TRACE: N=9 X=34 Y=55
> > > TRACE: N=10 X=55 Y=89
> > > TRACE: after fib loop (* A A)=100
> > > NIL
>
> > > Regards,
>
> > > Anthony
>
> > --http://lispm.dyndns.org/

Ok, here's the new macro:

(defmacro print-vars (&rest vars)
  "Prints variables listed in vars to *trace-output*.  If a string
is passed, it will be printed directly."
  `(progn (write-string "TRACE: " *trace-output*)
          ,@(loop for var in vars
               collect (if (stringp var)
                           `(progn (write-string ,var)(write-string "
"))
                           `(format *trace-output* "~A=~S "
',var ,var)))
          (terpri *trace-output*)
          (finish-output *trace-output*)))


Much smaller and cleaner now with your help.

And here's the new usage code:

CL-USER> (let ((a 10))
                   (print-vars "before fib loop" a "more stuff here")
                   (loop for n from 1 to a
                         for x = 1 then y
                         and y = 1 then (+ x y)
                         do (print-vars n x y "in loop!"))
                   (print-vars "after fib loop" (* a a)))
TRACE: before fib loop A=10 more stuff here
TRACE: N=1 X=1 Y=1 in loop!
TRACE: N=2 X=1 Y=2 in loop!
TRACE: N=3 X=2 Y=3 in loop!
TRACE: N=4 X=3 Y=5 in loop!
TRACE: N=5 X=5 Y=8 in loop!
TRACE: N=6 X=8 Y=13 in loop!
TRACE: N=7 X=13 Y=21 in loop!
TRACE: N=8 X=21 Y=34 in loop!
TRACE: N=9 X=34 Y=55 in loop!
TRACE: N=10 X=55 Y=89 in loop!
TRACE: after fib loop (* A A)=100


Here's a macroexpand:

CL-USER> (pprint (macroexpand-1 '(print-vars "before" a b c "after")))

(PROGN
  (WRITE-STRING "TRACE: " *TRACE-OUTPUT*)
  (PROGN (WRITE-STRING "before") (WRITE-STRING " "))
  (FORMAT *TRACE-OUTPUT* "~A=~S " 'A A)
  (FORMAT *TRACE-OUTPUT* "~A=~S " 'B B)
  (FORMAT *TRACE-OUTPUT* "~A=~S " 'C C)
  (PROGN (WRITE-STRING "after") (WRITE-STRING " "))
  (TERPRI *TRACE-OUTPUT*)
  (FINISH-OUTPUT *TRACE-OUTPUT*))
; No value

Thanks again!  Now I'm off to look at kenny's suggestions.

Anthony
From: Ken Tilton
Subject: Re: A simple debugging macro
Date: 
Message-ID: <yZW3j.17$jV3.2@newsfe09.lga>
·················@gmail.com wrote:
> Here's a macroexpand:
> 
> CL-USER> (pprint (macroexpand-1 '(print-vars "before" a b c "after")))
> 
> (PROGN
>   (WRITE-STRING "TRACE: " *TRACE-OUTPUT*)
>   (PROGN (WRITE-STRING "before") (WRITE-STRING " "))
>   (FORMAT *TRACE-OUTPUT* "~A=~S " 'A A)
>   (FORMAT *TRACE-OUTPUT* "~A=~S " 'B B)
>   (FORMAT *TRACE-OUTPUT* "~A=~S " 'C C)
>   (PROGN (WRITE-STRING "after") (WRITE-STRING " "))
>   (TERPRI *TRACE-OUTPUT*)
>   (FINISH-OUTPUT *TRACE-OUTPUT*))
> ; No value
> 

Which reminds me, you probably want the expnasion to be:

    (call-print-vars "before" a b c "after")

...and with mine, if the first arg is a hard-coded nil (not a form which 
might evaluate to nil at runtime, which would mean "do not emit this 
time") the expansion is:

   (progn)

Makes it quick and easy to disable/re-enable debug stuff I suspect will 
be needed again.

> Thanks again!  Now I'm off to look at kenny's suggestions.

If you like them you might want to start from the stuff in utils-kt. 
Less often needed but great when needed is a with-trc macro that wraps a 
possibly recursively invoked form such that output is indented to 
reflect recursion depth.

Another favorite of mine is

    (with-metrics <counts?> <timing?> <insert usual trc args> &body)

timing being t causes the form to be wrapped in (time ), counts being t 
invokes a counting utility, initializing it, running the body, and then 
dumping the count results. counting is easy:

    (count-it :hi-mom)

or

    (count-it :color-change this-color)

the latter giving you a histogram by color value.

kt

-- 
http://www.theoryyalgebra.com/

"In the morning, hear the Way;
  in the evening, die content!"
                     -- Confucius
From: ·················@gmail.com
Subject: Re: A simple debugging macro
Date: 
Message-ID: <1a8b17f8-3faa-4e7e-b8b6-8c403377972c@e10g2000prf.googlegroups.com>
On Nov 30, 8:34 am, Ken Tilton <···········@optonline.net> wrote:
> ·················@gmail.com wrote:
> > Here's a macroexpand:
>
> > CL-USER> (pprint (macroexpand-1 '(print-vars "before" a b c "after")))
>
> > (PROGN
> >   (WRITE-STRING "TRACE: " *TRACE-OUTPUT*)
> >   (PROGN (WRITE-STRING "before") (WRITE-STRING " "))
> >   (FORMAT *TRACE-OUTPUT* "~A=~S " 'A A)
> >   (FORMAT *TRACE-OUTPUT* "~A=~S " 'B B)
> >   (FORMAT *TRACE-OUTPUT* "~A=~S " 'C C)
> >   (PROGN (WRITE-STRING "after") (WRITE-STRING " "))
> >   (TERPRI *TRACE-OUTPUT*)
> >   (FINISH-OUTPUT *TRACE-OUTPUT*))
> > ; No value
>
> Which reminds me, you probably want the expnasion to be:
>
>     (call-print-vars "before" a b c "after")
>

Assuming CALL-PRINT-VARS is a function, wouldn't PRINT-VARS need to
expand to:

(call-print-vars "before" :a a :b b :c c "after")

Also, this case needs to be handled:

(print-vars (length my-list))

expands to:

(call-print-vars :|(length my-list)| (length my-list))

And would print:

TRACE: (LENGTH MY-LIST)=12

Is this correct or am I missing something?

> ...and with mine, if the first arg is a hard-coded nil (not a form which
> might evaluate to nil at runtime, which would mean "do not emit this
> time") the expansion is:
>
>    (progn)
>
> Makes it quick and easy to disable/re-enable debug stuff I suspect will
> be needed again.
>
> > Thanks again!  Now I'm off to look at kenny's suggestions.
>
> If you like them you might want to start from the stuff in utils-kt.
> Less often needed but great when needed is a with-trc macro that wraps a
> possibly recursively invoked form such that output is indented to
> reflect recursion depth.
>
> Another favorite of mine is
>
>     (with-metrics <counts?> <timing?> <insert usual trc args> &body)
>
> timing being t causes the form to be wrapped in (time ), counts being t
> invokes a counting utility, initializing it, running the body, and then
> dumping the count results. counting is easy:
>
>     (count-it :hi-mom)
>
> or
>
>     (count-it :color-change this-color)
>
> the latter giving you a histogram by color value.
>

This is very useful to me, I'll look at your utils-kt and see what I
can cook up with this.