clojure.stacktrace/root-cause VS clojure.repl/root-cause, are they redundant?

139 views
Skip to first unread message

Pierre Masci

unread,
Jul 21, 2014, 7:30:17 AM7/21/14
to clo...@googlegroups.com
Hi, I'm learning about tools to help me debug from the REPL, and I found these two with the same name:

    clojure.stacktrace/root-cause

    clojure.repl/root-cause

For a very simple case (wrong arity), they give pretty similar output:

    user=> (char 0 0 0)
    CompilerException clojure.lang.ArityException: Wrong number of args (3) passed to: core/char--inliner, compiling:(/tmp/form-init6819528724684564936.clj:1:1) 

    user=> (clojure.stacktrace/root-cause *e)
    #<ArityException clojure.lang.ArityException: Wrong number of args (3) passed to: core/char--inliner>

    user=> (clojure.repl/root-cause *e)
    #<CompilerException clojure.lang.ArityException: Wrong number of args (3) passed to: core/char--inliner, compiling:(/tmp/form-init6819528724684564936.clj:1:1)>


I looked at the source code and they look fairly similar, but I didn't understand the exact details.

If they do the same job, then which one does it best?

If they perform different roles, then could you describe the difference to a user who doesn't need to understand the internals? ( I'm happy to understand them if you are willing to explain, though :) )

Pierre Masci

unread,
Jul 21, 2014, 10:27:12 AM7/21/14
to clo...@googlegroups.com
I have now noticed that these two are also very similar:

    clojure.stacktrace/print-stack-trace

    clojure.repl/pst    ; (for Print Stack Trace)

Here is their output for the same error:

user=> (char 0 0 0)
CompilerException clojure.lang.ArityException: Wrong number of args (3) passed to: core/char--inliner, compiling:(/tmp/form-init9068522213039312274.clj:1:1) 

user=> (clojure.stacktrace/print-stack-trace *e)
clojure.lang.Compiler$CompilerException: clojure.lang.ArityException: Wrong number of args (3) passed to: core/char--inliner, compiling:(/tmp/form-init9068522213039312274.clj:1:1)
 at clojure.lang.Compiler.analyzeSeq (Compiler.java:6651)
    clojure.lang.Compiler.analyze (Compiler.java:6445)
    clojure.lang.Compiler.analyze (Compiler.java:6406)
    clojure.lang.Compiler$BodyExpr$Parser.parse (Compiler.java:5782)
    clojure.lang.Compiler$FnMethod.parse (Compiler.java:5217)
    clojure.lang.Compiler$FnExpr.parse (Compiler.java:3846)
    clojure.lang.Compiler.analyzeSeq (Compiler.java:6642)
    clojure.lang.Compiler.analyze (Compiler.java:6445)
    clojure.lang.Compiler.eval (Compiler.java:6700)
    clojure.lang.Compiler.eval (Compiler.java:6666)
    clojure.core$eval.invoke (core.clj:2927)
    clojure.main$repl$read_eval_print__6625$fn__6628.invoke (main.clj:239)
    clojure.main$repl$read_eval_print__6625.invoke (main.clj:239)
    clojure.main$repl$fn__6634.invoke (main.clj:257)
    clojure.main$repl.doInvoke (main.clj:257)
    clojure.lang.RestFn.invoke (RestFn.java:1096)
    clojure.tools.nrepl.middleware.interruptible_eval$evaluate$fn__591.invoke (interruptible_eval.clj:56)
    clojure.lang.AFn.applyToHelper (AFn.java:152)
    clojure.lang.AFn.applyTo (AFn.java:144)
    clojure.core$apply.invoke (core.clj:624)
    clojure.core$with_bindings_STAR_.doInvoke (core.clj:1862)
    clojure.lang.RestFn.invoke (RestFn.java:425)
    clojure.tools.nrepl.middleware.interruptible_eval$evaluate.invoke (interruptible_eval.clj:41)
    clojure.tools.nrepl.middleware.interruptible_eval$interruptible_eval$fn__632$fn__635.invoke (interruptible_eval.clj:171)
    clojure.core$comp$fn__4192.invoke (core.clj:2402)
    clojure.tools.nrepl.middleware.interruptible_eval$run_next$fn__625.invoke (interruptible_eval.clj:138)
    clojure.lang.AFn.run (AFn.java:22)
    java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1145)
    java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:615)
    java.lang.Thread.run (Thread.java:744)
nil
user=> (clojure.repl/pst *e)
CompilerException clojure.lang.ArityException: Wrong number of args (3) passed to: core/char--inliner, compiling:(/tmp/form-init9068522213039312274.clj:1:1)
        clojure.lang.Compiler.analyzeSeq (Compiler.java:6651)
        clojure.lang.Compiler.analyze (Compiler.java:6445)
        clojure.lang.Compiler.analyze (Compiler.java:6406)
        clojure.lang.Compiler$BodyExpr$Parser.parse (Compiler.java:5782)
        clojure.lang.Compiler$FnMethod.parse (Compiler.java:5217)
        clojure.lang.Compiler$FnExpr.parse (Compiler.java:3846)
        clojure.lang.Compiler.analyzeSeq (Compiler.java:6642)
        clojure.lang.Compiler.analyze (Compiler.java:6445)
        clojure.lang.Compiler.eval (Compiler.java:6700)
        clojure.lang.Compiler.eval (Compiler.java:6666)
        clojure.core/eval (core.clj:2927)
        clojure.main/repl/read-eval-print--6625/fn--6628 (main.clj:239)
Caused by:
ArityException Wrong number of args (3) passed to: core/char--inliner
        clojure.lang.Compiler.analyzeSeq (Compiler.java:6639)
        clojure.lang.Compiler.analyze (Compiler.java:6445)
        clojure.lang.Compiler.analyze (Compiler.java:6406)
        clojure.lang.Compiler$BodyExpr$Parser.parse (Compiler.java:5782)
        clojure.lang.Compiler$FnMethod.parse (Compiler.java:5217)
        clojure.lang.Compiler$FnExpr.parse (Compiler.java:3846)
nil

The top part of their output is the same, but not the bottom.
If no-one comes up with an explanation, I'll use both until I understand which one is more useful to me, and report back here if I remember (hopefully!)

Stuart Sierra

unread,
Jul 24, 2014, 8:33:42 AM7/24/14
to clo...@googlegroups.com
They're just different versions of the same thing, written at different times by different people, that both got merged into Clojure at different times.

Speaking as the original author of clojure.stacktrace, I now think neither one of them should exist. The .printStackTrace method on an exception gives you all the same information and is more reliable.

-S

mascip

unread,
Jul 24, 2014, 9:47:34 AM7/24/14
to clo...@googlegroups.com
Thank you Stuart, this is a very useful answer.

Is there any way to access an exception older than *e? 
What happens to me regularly is to mistype (.printStackTrace *e), which makes me lost my previous exception.

-- Pierre Masci


--
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
---
You received this message because you are subscribed to a topic in the Google Groups "Clojure" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/clojure/Ic-49W9ZEac/unsubscribe.
To unsubscribe from this group and all its topics, send an email to clojure+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Andy Fingerhut

unread,
Jul 24, 2014, 10:48:20 AM7/24/14
to clo...@googlegroups.com
I know of no way that older exceptions than *e are automatically saved anywhere (unlike the results of previous REPL expressions, of which the last 3 are saved in *1 *2 *3).

When an exception occurs, it is probably much less error-prone to type a short expression like (def e1 *e) to save the exception in e1, even if another exception occurs after that which modifies *e.

Andy


You received this message because you are subscribed to the Google Groups "Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email to clojure+u...@googlegroups.com.

mascip

unread,
Jul 24, 2014, 7:07:33 PM7/24/14
to clo...@googlegroups.com

Saving *e in a def for further investigation, handy :) Cheers

Reply all
Reply to author
Forward
0 new messages