2010-10-31 21 views
19

Lorsque j'exécute mes programmes Clojure et que j'obtiens une erreur lors de l'exécution, je remarque que le message imprimé par REPL contient uniquement le numéro de ligne de niveau supérieur du script que j'ai exécuté. Puis-je l'obtenir pour vider une pile d'appels (qui fait référence aux différents numéros de ligne du code Clojure)?Obtenir une pile d'appel dans Clojure

Par exemple:

user=> (load-file "test.clj") 
java.lang.IllegalArgumentException: Wrong number of args (1) passed to: user$eval134$fn (test.clj:206) 
user=> 

Ce serait mieux si je savais plus que l'appel de haut niveau (ligne 206).

Répondre

28

La dernière exception affichée est disponible dans la variable *e var. Vous pouvez imprimer une trace de pile en appelant le .printStackTrace à l'exception. Il imprimera les numéros de ligne si votre exception a été lancée par le code source dans un fichier, ou NO_SOURCE_FILE si elle provient de REPL, comme dans mes exemples ci-dessous. il y a une fonction appelée pst qui fait la même chose

Clojure 1.2.0 
user=> (throw (Exception. "FOO")) 
java.lang.Exception: FOO (NO_SOURCE_FILE:0) 
user=> *e 
#<CompilerException java.lang.Exception: FOO (NO_SOURCE_FILE:0)> 
user=> (.printStackTrace *e) 
java.lang.Exception: FOO (NO_SOURCE_FILE:0) 
     at clojure.lang.Compiler.eval(Compiler.java:5440) 
     at clojure.lang.Compiler.eval(Compiler.java:5391) 
     at clojure.core$eval.invoke(core.clj:2382) 
     at clojure.main$repl$read_eval_print__5624.invoke(main.clj:183) 
     at clojure.main$repl$fn__5629.invoke(main.clj:204) 
     at clojure.main$repl.doInvoke(main.clj:204) 
     at clojure.lang.RestFn.invoke(RestFn.java:422) 
     at clojure.main$repl_opt.invoke(main.clj:262) 
     at clojure.main$main.doInvoke(main.clj:355) 
     at clojure.lang.RestFn.invoke(RestFn.java:398) 
     at clojure.lang.Var.invoke(Var.java:361) 
     at clojure.lang.AFn.applyToHelper(AFn.java:159) 
     at clojure.lang.Var.applyTo(Var.java:482) 
     at clojure.main.main(main.java:37) 
Caused by: java.lang.Exception: FOO 
     at user$eval1.invoke(NO_SOURCE_FILE:1) 
     at clojure.lang.Compiler.eval(Compiler.java:5424) 
     ... 13 more 
nil 

Dans Clojure 1.3 (alpha de). Ces traces de pile sont un peu plus belles car certaines lignes superflues sont supprimées.

Clojure 1.3.0-master-SNAPSHOT 
user=> (throw (Exception. "FOO")) 
Exception FOO user/eval1 (NO_SOURCE_FILE:1) 
user=> (pst) 
Exception FOO 
     user/eval1 (NO_SOURCE_FILE:1) 
     clojure.lang.Compiler.eval (Compiler.java:5998) 
     clojure.lang.Compiler.eval (Compiler.java:5965) 
     clojure.core/eval (core.clj:2652) 
     clojure.core/eval (core.clj:-1) 
     clojure.main/repl/read-eval-print--5575 (main.clj:178) 
     clojure.main/repl/fn--5580 (main.clj:199) 
     clojure.main/repl (main.clj:199) 
     clojure.main/repl-opt (main.clj:257) 
     clojure.main/main (main.clj:350) 
     clojure.lang.Var.invoke (Var.java:361) 
     clojure.lang.Var.applyTo (Var.java:482) 
nil 

Certains IDE (par exemple SLIME pour Emacs) afficheront automatiquement la trace de la pile. Il existe également des bibliothèques pour l'affichage et la manipulation des stacktraces, telles que clojure.stacktrace et clj-stacktrace.

La gestion des traces de pile semble être un aspect de Clojure qui est en cours de raffinage.

+0

Fonctionne parfaitement! :) – pauldoo

+0

Existe-t-il un moyen d'accéder aux exceptions passées, autres que * e? – mascip