simple debugging utility

0 views
Skip to first unread message

Mark Volkmann

unread,
Mar 24, 2009, 10:43:35 AM3/24/09
to clo...@googlegroups.com
I want to write a function or macro that allows me to output the value
of an expression without repeating it. For example, I want something
like (dump (+ 1 2)) to output "(+ 1 2) = 3".

This works.

(defn dump1 [string]
(println string "=" (load-string string)))
(dump1 "(+ 1 2)")

Note how I had to put the expression passed to dump1 in quotes to make a string.

I'm wondering if there is a way to avoid that using a macro. The hard
part is printing the expression. The following doesn't work. It
outputs "3 = 3".

(defmacro dump2 [expr]
`(let [value# ~expr]
(pr ~expr)
(println " =" value#)))
(dump2 (+ 1 2))

--
R. Mark Volkmann
Object Computing, Inc.

Mark Volkmann

unread,
Mar 24, 2009, 10:44:07 AM3/24/09
to clo...@googlegroups.com

Konrad Hinsen

unread,
Mar 24, 2009, 10:55:57 AM3/24/09
to clo...@googlegroups.com
On Mar 24, 2009, at 15:44, Mark Volkmann wrote:

> I'm wondering if there is a way to avoid that using a macro. The hard
> part is printing the expression. The following doesn't work. It
> outputs "3 = 3".
>
> (defmacro dump2 [expr]
> `(let [value# ~expr]
> (pr ~expr)
> (println " =" value#)))
> (dump2 (+ 1 2))

All it takes to make it work is a slight modification:

(defmacro dump [expr]
`(let [value# ~expr]
(pr (quote ~expr))
(println " =" value#)))

(dump (+ 1 2))

prints:

(+ 1 2) = 3

Konrad.

Mark Volkmann

unread,
Mar 24, 2009, 11:00:30 AM3/24/09
to clo...@googlegroups.com

Thanks! It looks like I don't need the let now. Does a macro have to
evaluate to one form? For example, this works, but it seems I can't
drop the do.

(defmacro dump [expr]
`(do
(print (quote ~expr))
(println " =" ~expr)))

Lauri Pesonen

unread,
Mar 24, 2009, 11:08:42 AM3/24/09
to clo...@googlegroups.com
2009/3/24 Mark Volkmann <r.mark....@gmail.com>:

>
> Thanks! It looks like I don't need the let now. Does a macro have to
> evaluate to one form? For example, this works, but it seems I can't
> drop the do.
>
> (defmacro dump [expr]
>  `(do
>     (print (quote ~expr))
>     (println " =" ~expr)))

How about:

(defmacro dump [expr]
`(println '~expr "=" ~expr))

> R. Mark Volkmann

--
! Lauri

Konrad Hinsen

unread,
Mar 24, 2009, 11:14:30 AM3/24/09
to clo...@googlegroups.com
On Mar 24, 2009, at 16:00, Mark Volkmann wrote:

> Thanks! It looks like I don't need the let now.

Indeed.

> Does a macro have to evaluate to one form? For example, this works,
> but it seems I can't
> drop the do.

Yes, a macro has to evaluate to one form. This is actually not so
much a condition on macros as a consequence of the fact that a macro,
like any function, has a single return value. What else could that
reasonably be but a form?

Konrad.

Joshua Fox

unread,
Mar 24, 2009, 11:32:26 AM3/24/09
to clo...@googlegroups.com
Eric Rochester has a debug macro, together with a walkthrough of how he built it, here

Joshua

Tom Faulhaber

unread,
Mar 24, 2009, 12:57:56 PM3/24/09
to Clojure
For reference, here's a version I wrote while I was working on cl-
format and the pretty printer:

(defn prerr [& args]
"Println to *err*"
(binding [*out* *err*]
(apply println args)))

(defmacro prlabel [prefix arg & more-args]
"Print args to *err* in name = value format"
(cons 'prerr (cons (list 'quote prefix) (mapcat #(list (list 'quote
%) "=" %)
(cons arg more-
args)))))

It prints a label (which is a string, but the macro quotes it for you
and a set of forms you want to print.

Using the above example, this would be (prlabel foo (+ 1 2)) and it
would print:
foo (+ 1 2) = 3

A real example from the PrettyWriter is:

(prlabel tf? (.getColumn this) (buffer-length tokens))

I make sure the output goes to *err* partially because that just seems
right for trace output and partially because cl-format tends to have
*out* bound at its whim.

Tom

On Mar 24, 8:32 am, Joshua Fox <joshuat...@gmail.com> wrote:
> Eric Rochester has a debug macro, together with a walkthrough of how he
> built it, herehttp://writingcoding.blogspot.com/2008/09/stemming-part-19-debugging....
>
> Joshua

Meikel Brandmeyer

unread,
Mar 24, 2009, 4:18:52 PM3/24/09
to clo...@googlegroups.com
Hi,

Am 24.03.2009 um 16:00 schrieb Mark Volkmann:

> Thanks! It looks like I don't need the let now.

But there are reasons to keep it! Eg. returning the expression
result!

(defmacro dump
[expr]
`(let [value# ~expr]

(println (pr-str (quote ~expr)) "=" (pr-str value#))
value#))

Then you can mix in your dump macro where you want.
Your version always returns nil.

Or you can have a look at clojure.contrib.trace.

Sincerely
Meikel

Reply all
Reply to author
Forward
0 new messages