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
·················@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
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")
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 ..."
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
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
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/
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/
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
·················@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
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.