Debugging in Clojure

165 views
Skip to first unread message

ajay gopalakrishnan

unread,
Jan 21, 2010, 8:14:47 PM1/21/10
to clo...@googlegroups.com
Hi,

I usually debug by adding println statements. How can I achieve the same effect in Clojure. I don't think I can introduce println at arbitrary places to figure out at which step is the algorithm failing.

Thanks,
Ajay

Richard Newman

unread,
Jan 21, 2010, 8:25:24 PM1/21/10
to clo...@googlegroups.com
> I usually debug by adding println statements. How can I achieve the
> same effect in Clojure. I don't think I can introduce println at
> arbitrary places to figure out at which step is the algorithm failing.

Sure you can. You might need to add a (do ) block if you're wanting to
add them in an (if), but that's no different to any other form in an
(if).

The only other consideration is laziness: your printlns might not fire
when you think they should.

ajay gopalakrishnan

unread,
Jan 21, 2010, 8:27:12 PM1/21/10
to clo...@googlegroups.com
Is this the preferred way of debugging in Clojure?

--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clo...@googlegroups.com
Note that posts from new members are moderated - please be patient with your first post.
To unsubscribe from this group, send email to
clojure+u...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

.Bill Smith

unread,
Jan 21, 2010, 8:48:16 PM1/21/10
to Clojure
I don't know about *the* preferred way, but it's my preferred way.
It's a no-brainer to add print statements. I believe there is at
least one logging library available too.

On Jan 21, 7:27 pm, ajay gopalakrishnan <ajgop...@gmail.com> wrote:
> Is this the preferred way of debugging in Clojure?
>

> On Thu, Jan 21, 2010 at 5:25 PM, Richard Newman <holyg...@gmail.com> wrote:
> > I usually debug by adding println statements. How can I achieve the same
> >> effect in Clojure. I don't think I can introduce println at arbitrary places
> >> to figure out at which step is the algorithm failing.
>
> > Sure you can. You might need to add a (do ) block if you're wanting to add
> > them in an (if), but that's no different to any other form in an (if).
>
> > The only other consideration is laziness: your printlns might not fire when
> > you think they should.
>
> > --
> > You received this message because you are subscribed to the Google
> > Groups "Clojure" group.
> > To post to this group, send email to clo...@googlegroups.com
> > Note that posts from new members are moderated - please be patient with
> > your first post.
> > To unsubscribe from this group, send email to

> > clojure+u...@googlegroups.com<clojure%2Bunsu...@googlegroups.com>

ataggart

unread,
Jan 21, 2010, 9:46:58 PM1/21/10
to Clojure
Logging side-effects usually occur within a do block, or the
equivalent, e.g., when, catch. For production code, I'd suggest a
logging library instead of filling your code with printlns. Contrib
has a logging lib that delegates to common java logging libraries, but
allows for writing them in a more idiomatic way.

http://richhickey.github.com/clojure-contrib/logging-api.html

David Nolen

unread,
Jan 22, 2010, 12:38:29 AM1/22/10
to clo...@googlegroups.com
I find that injecting print statements is painful if you're not using something like paredit (Emacs). With paredit it's quite simple.

Miron Brezuleanu

unread,
Jan 22, 2010, 3:08:45 AM1/22/10
to clo...@googlegroups.com
Hello,

On Fri, Jan 22, 2010 at 3:14 AM, ajay gopalakrishnan <ajgo...@gmail.com> wrote:
Hi,

I usually debug by adding println statements. How can I achieve the same effect in Clojure. I don't think I can introduce println at arbitrary places to figure out at which step is the algorithm failing.

I also use 'do's as others have suggested. Another trick is to add dummy variables in lets just to be able to print something. For instance,

(let [a 1
       b 2
       dummy1 (println "stuff")
       c 3]
  ...)

(this could be done by putting the 2 for b in a do and adding the println in the do, but that would be more invasive - with the dummy variable, it's just add/uncomment or  delete/comment out one line).

There's also the alternative of adding debug repls, which IMO is in the spirit of adding printlns, just better if you want interactivity.

http://groups.google.com/group/clojure/browse_thread/thread/8d77ad0da8d190c8/baf2a0bdf87b7dd6?lnk=gst&q=repl+macro#baf2a0bdf87b7dd6

(sorry for the long URL)

also
http://georgejahad.com/clojure/debug-repl-macros.html

for macros.

Thanks,
Ajay
--
Miron Brezuleanu

Heinz N. Gies

unread,
Jan 22, 2010, 6:28:14 AM1/22/10
to clo...@googlegroups.com
On Jan 22, 2010, at 9:08 , Miron Brezuleanu wrote:

> I also use 'do's as others have suggested. Another trick is to add dummy variables in lets just to be able to print something. For instance,
>
> (let [a 1
> b 2
> dummy1 (println "stuff")
> c 3]
> ...)


Isn't the ideomatic way here to call not used (dummy) variables _ (underscore)?

Konrad Scorciapino

unread,
Jan 22, 2010, 1:45:12 AM1/22/10
to clojure
(comment) and #_ are pretty useful to disable forms when debugging:

(+ 3 #_4) -> 3
(comment println "hi") -> nil

Excerpts from David Nolen's message of Fri Jan 22 02:38:29 -0300 2010:


> I find that injecting print statements is painful if you're not using
> something like paredit (Emacs). With paredit it's quite simple.
>
> On Thu, Jan 21, 2010 at 8:27 PM, ajay gopalakrishnan <ajgo...@gmail.com>wrote:
>
> > Is this the preferred way of debugging in Clojure?
> >
> >
> > On Thu, Jan 21, 2010 at 5:25 PM, Richard Newman <holy...@gmail.com>wrote:
> >
> >> I usually debug by adding println statements. How can I achieve the same
> >>> effect in Clojure. I don't think I can introduce println at arbitrary places
> >>> to figure out at which step is the algorithm failing.
> >>>
> >>
> >> Sure you can. You might need to add a (do ) block if you're wanting to add
> >> them in an (if), but that's no different to any other form in an (if).
> >>
> >> The only other consideration is laziness: your printlns might not fire
> >> when you think they should.
> >>
> >> --
> >> You received this message because you are subscribed to the Google
> >> Groups "Clojure" group.
> >> To post to this group, send email to clo...@googlegroups.com
> >> Note that posts from new members are moderated - please be patient with
> >> your first post.
> >> To unsubscribe from this group, send email to

> >> clojure+u...@googlegroups.com<clojure%2Bunsu...@googlegroups.com>


> >> For more options, visit this group at
> >> http://groups.google.com/group/clojure?hl=en
> >
> >
> > --
> > You received this message because you are subscribed to the Google
> > Groups "Clojure" group.
> > To post to this group, send email to clo...@googlegroups.com
> > Note that posts from new members are moderated - please be patient with
> > your first post.
> > To unsubscribe from this group, send email to

> > clojure+u...@googlegroups.com<clojure%2Bunsu...@googlegroups.com>

Krukow

unread,
Jan 22, 2010, 7:40:52 AM1/22/10
to Clojure

On Jan 22, 2:27 am, ajay gopalakrishnan <ajgop...@gmail.com> wrote:
> Is this the preferred way of debugging in Clojure?

Please don't top post.

I've heard people have success with regular debuggers, e.g. JSwat,
although I haven't tried this myself...

/Karl

Mike Meyer

unread,
Jan 22, 2010, 7:13:51 PM1/22/10
to clo...@googlegroups.com
On Fri, 22 Jan 2010 10:08:45 +0200
Miron Brezuleanu <mbr...@gmail.com> wrote:

> Hello,
>
> On Fri, Jan 22, 2010 at 3:14 AM, ajay gopalakrishnan <ajgo...@gmail.com>wrote:
>
> > Hi,
> >
> > I usually debug by adding println statements. How can I achieve the same
> > effect in Clojure. I don't think I can introduce println at arbitrary places
> > to figure out at which step is the algorithm failing.
> >
>
> I also use 'do's as others have suggested. Another trick is to add dummy
> variables in lets just to be able to print something. For instance,
>
> (let [a 1
> b 2
> dummy1 (println "stuff")
> c 3]
> ...)
>
> (this could be done by putting the 2 for b in a do and adding the println in
> the do, but that would be more invasive - with the dummy variable, it's just
> add/uncomment or delete/comment out one line).
>

Um, I'm surprised that no one has mentioned clojure.contrib.trace.
Given that Clojure is mostly functional, those "debugging" printlns
will mostly be arguments to functions, or values coming out of
them. The trace package lets you evaluate an expression at the repl,
tracing the values in and out of a user-specified set of functions
during the evaluation process.

That's what I'd consider the idiomatic way to do debugging in a LISP.

<mike
--
Mike Meyer <m...@mired.org> http://www.mired.org/consulting.html
Independent Network/Unix/Perforce consultant, email for more information.

O< ascii ribbon campaign - stop html mail - www.asciiribbon.org

ataggart

unread,
Jan 22, 2010, 8:04:28 PM1/22/10
to Clojure

On Jan 22, 4:13 pm, Mike Meyer <mwm-keyword-googlegroups.


620...@mired.org> wrote:
> On Fri, 22 Jan 2010 10:08:45 +0200
>
>
>
>
>
> Miron Brezuleanu <mbr...@gmail.com> wrote:
> > Hello,
>

I haven't used c.c.trace since it can't be left in place without a
performance hit. It seems like it might be useful at the repl, but I
haven't figured out how to make it do anything interesting, e.g.:

user=> (defn foo [coll] (reduce + coll))
#'user/bar
user=> (defn bar [coll] (map inc coll))
#'user/foo
user=> (trace (foo (bar [1 1 1])))
TRACE: 6
6

Given that trace is a function and not a macro, this result isn't
surprising. I'm sure there *is* a way to actually trace such a call,
but I haven't figured it out. It occurs to me that such functionality
might be worth dropping into c.c.logging, something akin to the spy
macro. At least then we could leave the code in place.

ajay gopalakrishnan

unread,
Jan 22, 2010, 8:25:39 PM1/22/10
to clo...@googlegroups.com
I dont mind using println. The problem is that needs to be inside a do or when ... and that is not really part of my code. When the time comes to remove the prints, i need to remove all these do blocks too. I can leave them as it is I guess, but then it is not neat and non-idiomatic. From all the replies, it seems that Debugging is going to be a pain in the Lisp style languages. How do people in Lisp/Scheme debug it?

--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clo...@googlegroups.com
Note that posts from new members are moderated - please be patient with your first post.
To unsubscribe from this group, send email to
clojure+u...@googlegroups.com

ataggart

unread,
Jan 22, 2010, 8:38:33 PM1/22/10
to Clojure

> > clojure+u...@googlegroups.com<clojure%2Bunsu...@googlegroups.com >


> > For more options, visit this group at
> >http://groups.google.com/group/clojure?hl=en

Debugging is not exactly the same as logging (though the latter might
help with the former). I infer you mean logging, hence you should use
a logging library that allows you to *leave* the log calls in the code
such that they to be enabled/disabled via configuration, but have
negligible performance impact when disabled.

See http://richhickey.github.com/clojure-contrib/logging-api.html

Stefan Kamphausen

unread,
Jan 22, 2010, 9:07:39 PM1/22/10
to Clojure
Hi,

On Jan 22, 2:14 am, ajay gopalakrishnan <ajgop...@gmail.com> wrote:
> I usually debug by adding println statements.

if you use Emacs is this statement is true for other programming
languages, too, you might be interested in using lldebug. I'm pretty
sure, that when you ask the author to add support for Clojure he will.

See
http://www.cbrunzema.de/download/ll-debug/ll-debug.el

> How can I achieve the same
> effect in Clojure. I don't think I can introduce println at arbitrary places
> to figure out at which step is the algorithm failing.

I'm with you here. I'm almost sure, I've come across situations in
which *out* must have been bound to something else, if you are using
Emacs/Slime make sure to search the buffer *inferior-lisp* for missing
output.

Coming from Common Lisp and Slime I'm rather used to do all my
debugging in Emacs and Slime, too. Really. That stacktrace-explorer
is really good. However, I think that Rich Hickey thinks the Java
debugging tools should be used with Clojure, too. No need to code
something like that, right now, Clojure is just too young. I haven't
tried them yet, but will in the near future. Probably YourKit. Maybe
you want to go that way, too?

Kind regards,
Stefan

Mike Meyer

unread,
Jan 22, 2010, 9:27:15 PM1/22/10
to clo...@googlegroups.com, ajgo...@gmail.com
On Fri, 22 Jan 2010 17:25:39 -0800
ajay gopalakrishnan <ajgo...@gmail.com> wrote:

> I dont mind using println. The problem is that needs to be inside a do or
> when ... and that is not really part of my code. When the time comes to
> remove the prints, i need to remove all these do blocks too. I can leave
> them as it is I guess, but then it is not neat and non-idiomatic. From all
> the replies, it seems that Debugging is going to be a pain in the Lisp style
> languages. How do people in Lisp/Scheme debug it?

In the REPL. That's a pretty complete debugger, all by itself. In
something like SLIME, you get the ability to examine the call stack,
etc. while things are running.

The trace package just dumps arguments/results of functions while they
run. It's a primitive tool, but better than println's in many cases:

user it, then use dotrace:

user> (use 'clojure.contrib.trace)
nil
user> (defn foo [coll] (reduce + coll))
#'user/foo
user> (defn bar [coll] (map inc coll))
#'user/bar
user> (dotrace [foo bar] (foo (bar [1 1 1])))
TRACE t7043: (bar [1 1 1])
TRACE t7043: => (2 2 2)
TRACE t7044: (foo (2 2 2))
TRACE t7044: => 6
6
user> (dotrace [foo +] (foo (bar [1 1 1])))
TRACE t7071: (foo (2 2 2))
TRACE t7072: | (+ 2 2)
TRACE t7072: | => 4
TRACE t7073: | (+ 4 2)
TRACE t7073: | => 6
TRACE t7071: => 6
6

and so on.

ataggart

unread,
Jan 23, 2010, 12:02:13 AM1/23/10
to Clojure

On Jan 22, 6:27 pm, Mike Meyer <mwm-keyword-googlegroups.


620...@mired.org> wrote:
> On Fri, 22 Jan 2010 17:25:39 -0800
>

See, I *knew* there had to be a way to do it! Clearly I wasn't
grokking the docs for dotrace. If the authors of of c.c.trace are
amenable, I'm inclined to add this functionality to a variant of the
c.c.logging/spy macro, something like:

(spy [foo bar] (foo (bar [1 1 1])))

Jeff Rose

unread,
Jan 23, 2010, 7:26:56 AM1/23/10
to Clojure
On Jan 22, 1:40 pm, Krukow <karl.kru...@gmail.com> wrote:
> Please don't top post.

Seriously, people still complain about this? It's the default
behavior in Google Groups, so I think you just have to live with it.
Find a news reader that doesn't suck.

Timothy Pratley

unread,
Jan 24, 2010, 6:11:21 AM1/24/10
to clo...@googlegroups.com
2010/1/23 ataggart <alex.t...@gmail.com>:

> If the authors of of c.c.trace are
> amenable, I'm inclined to add this functionality to a variant of the
> c.c.logging/spy macro

Great idea!

Gabi

unread,
Jan 24, 2010, 8:22:00 AM1/24/10
to Clojure
Be careful of deftrace. It has a bug that crashes when the defn'ed
funcs have string comment on the top of the func

e

unread,
Jan 24, 2010, 11:16:17 AM1/24/10
to clo...@googlegroups.com
It has confused me since the day I tried to mess around with clojure that this topic isn't brought up more (not that I follow clj regularly) ... so I'm happy to learn that someone added trace capabilities.

That said (and I'm not trying to make this a "charged" statement ... just a way to learn more) I had always thought that one of the key things that made lisp so complete was that programs don't just crash ... that debugging is fully-baked into the *core* of everything.  Now, I don't remember much about the debugging capabilities of, say, CL, but my understanding is that *after* a crash, you can interrogate the state of objects. . . .rather than having to preemptively guess at what you may want to know in the future.

Trace is better than logging.  Logging just seems like a flawed approach (as others have pointed out).  I mean, Log4j (or related) is desired in Java so that someone can get more information without a recompile.  But in a dynamically run language or in an environment where you aren't just the user of some closed-off code, you may as well just put print statements where you need them.  The latter is what I was advised to do in Clojure, and it was a real turn-off for me.  Maybe the lack of appeal comes from having to squeeze in that extra "do" nesting -- or maybe because you then have to go through and remove all that stuff later.  Or in the case of logging? you always leave it there, FOREVER.  Even if you never end up caring about some state in a production environment!!!

So, anyway, it seems to me that folks have been successfully chipping away, borrowing, and improving the cool things about CL for years, but, amazingly, a newb to Lisp like me can still find something unique about CL.  Or, at least it seems unique to me .... this concept of leaving the user suspended in the middle of the execution exactly where it crashes without having to know before-hand that they should have somehow debugged.  It's the only language I know of that comes that close to giving you the true state of a program "when it crashed".  I mean, any time you have to rerun a program, you have to say, "I hope I can repeat (or remember) the conditions".

But maybe there are things I'm not considering.  It seems like an FP-lang ought to be able to handle something like that environment easily.  On the other hand, a parallel world could have real troubles bothering to trying to figure out what any of that would mean.

I wonder how CL users feel about this issue.  Is it a feature they really love or something they wouldn't miss because they never really took advantage of it?



Richard Newman

unread,
Jan 24, 2010, 2:08:51 PM1/24/10
to clo...@googlegroups.com
> That said (and I'm not trying to make this a "charged" statement ...
> just a way to learn more) I had always thought that one of the key
> things that made lisp so complete was that programs don't just
> crash ... that debugging is fully-baked into the *core* of
> everything. Now, I don't remember much about the debugging
> capabilities of, say, CL, but my understanding is that *after* a
> crash, you can interrogate the state of objects. . . .rather than
> having to preemptively guess at what you may want to know in the
> future.

This is largely down to CL's condition system: problems are usually
reported as conditions, which stop execution without unwinding the
stack. Unlike exceptions, you typically get a REPL in the environment
of the condition (so you can view locals, inspect objects, etc.) — a
bit like being "dropped into the debugger" in an IDE. Unlike an IDE,
you can *do things* to the running program, and the condition often
offers restarts (e.g., a "compile failed" condition might offer to
retry the compilation). That means you can fix and continue, or just
find out what went wrong.

These make an unexpected condition into an interactive process, rather
than merely an opportunity for logging. By the time you were ready to
ship your app, you'd experienced most of the failures, and introduced
static or dynamic handling for those problems.

Unfortunately, Java can't match CL's condition system. There are steps
towards including some of its power in Clojure (see errorkit).

That said, I still use tracing extensively in Common Lisp development:
things might not crash, but I still need to see what's going on to
identify the root cause of some high-level behavior. I also use print
statements: often trace output is too verbose, or I need to see the
result of some computation on an intermediate value. Sometimes there's
no condition to raise.

> Trace is better than logging. Logging just seems like a flawed
> approach (as others have pointed out). I mean, Log4j (or related)
> is desired in Java so that someone can get more information without
> a recompile. But in a dynamically run language or in an environment
> where you aren't just the user of some closed-off code, you may as
> well just put print statements where you need them. The latter is
> what I was advised to do in Clojure, and it was a real turn-off for
> me. Maybe the lack of appeal comes from having to squeeze in that
> extra "do" nesting -- or maybe because you then have to go through
> and remove all that stuff later. Or in the case of logging? you
> always leave it there, FOREVER. Even if you never end up caring
> about some state in a production environment!!!

I disagree that logging is a flawed approach. Tracing is an
interactive tool. Logging allows you to see what happened before you
were watching (which is important in the case of systems that are
running for months or years, on many different machines, handling
millions of requests). It also helps to produce a usable record of
events in your program, which aren't always visible in trace output —
e.g., "this request was invalid because this header appears to be
truncated". Try spotting that in trace output.

e

unread,
Jan 24, 2010, 2:50:44 PM1/24/10
to clo...@googlegroups.com
interesting.  thanks for the thoughtful reply.


--
Reply all
Reply to author
Forward
0 new messages