Joh*_*den 156
还有dotrace,它允许您查看所选功能的输入和输出.
(use 'clojure.contrib.trace)
(defn fib[n] (if (< n 2) n (+ (fib (- n 1)) (fib (- n 2)))))
(dotrace [fib] (fib 3))
Run Code Online (Sandbox Code Playgroud)
产生输出:
TRACE t4425: (fib 3)
TRACE t4426: | (fib 2)
TRACE t4427: | | (fib 1)
TRACE t4427: | | => 1
TRACE t4428: | | (fib 0)
TRACE t4428: | | => 0
TRACE t4426: | => 1
TRACE t4429: | (fib 1)
TRACE t4429: | => 1
TRACE t4425: => 2
2
Run Code Online (Sandbox Code Playgroud)
在Clojure 1.4中,dotrace
已经移动:
你需要依赖:
[org.clojure/tools.trace "0.7.9"]
(require 'clojure.tools.trace)
Run Code Online (Sandbox Code Playgroud)
您需要将^:dynamic添加到函数定义中
(defn ^:dynamic fib[n] (if (< n 2) n (+ (fib (- n 1)) (fib (- n 2)))))
Run Code Online (Sandbox Code Playgroud)
然后鲍勃又是你的叔叔:
(clojure.tools.trace/dotrace [fib] (fib 3))
TRACE t4328: (fib 3)
TRACE t4329: | (fib 2)
TRACE t4330: | | (fib 1)
TRACE t4330: | | => 1
TRACE t4331: | | (fib 0)
TRACE t4331: | | => 0
TRACE t4329: | => 1
TRACE t4332: | (fib 1)
TRACE t4332: | => 1
TRACE t4328: => 2
Run Code Online (Sandbox Code Playgroud)
Joh*_*den 100
我有一个小调试宏,我觉得非常有用:
;;debugging parts of expressions
(defmacro dbg[x] `(let [x# ~x] (println "dbg:" '~x "=" x#) x#))
Run Code Online (Sandbox Code Playgroud)
您可以将它插入任何想要观察的内容和时间:
;; Examples of dbg
(println (+ (* 2 3) (dbg (* 8 9))))
(println (dbg (println "yo")))
(defn factorial[n] (if (= n 0) 1 (* n (dbg (factorial (dec n))))))
(factorial 8)
(def integers (iterate inc 0))
(def squares (map #(dbg(* % %)) integers))
(def cubes (map #(dbg(* %1 %2)) integers squares))
(take 5 cubes)
(take 5 cubes)
Run Code Online (Sandbox Code Playgroud)
Mic*_*zyk 46
我最喜欢的方法是println
在代码中自由地散布各种代码...... 由于读取器宏(这使得读者以下面的形式阅读,然后假装它从未见过它),打开和关闭它们很容易#_
.或者您可以使用宏扩展到传入的主体或nil
根据某些特殊变量的值,例如*debug*
:
(defmacro debug-do [& body]
(when *debug*
`(do ~@body)))
Run Code Online (Sandbox Code Playgroud)
随着(def *debug* false)
在那里,这将扩展到nil
.随着true
它,它将扩展到body
包裹在do
.
这个SO问题的公认答案:进展报告的惯用语Clojure?在调试序列操作时非常有用.
然后有一些东西目前与swank-clojure的REPL 不兼容,但是太好了,更不用说了:debug-repl
.您可以在独立的REPL中使用它,这很容易获得,例如Leiningen(lein repl
); 如果您从命令行启动程序,那么它将在您的终端中直接启用自己的REPL.我们的想法是,您可以将debug-repl
宏放在任何您喜欢的地方,并在程序执行到达该点时启动它自己的REPL,所有本地人都在范围内等.几个相关链接:Clojure debug-repl,Clojure调试-repl技巧,如何在Clojars上调试repl(在Clojure Google组上),调试代理.
使用Clojure代码时,swank-clojure能够使SLIME的内置调试器变得非常有用 - 请注意堆栈跟踪的不相关位是如何变灰的,因此很容易在被调试的代码中找到实际问题.要记住的一件事是,没有"名称标签"的匿名函数出现在堆栈跟踪中,基本上没有附加有用的信息; 当添加"名称标签"时,它会出现在堆栈跟踪中,并且一切都很好:
(fn [& args] ...)
vs.
(fn tag [& args] ...)
example stacktrace entries:
1: user$eval__3130$fn__3131.invoke(NO_SOURCE_FILE:1)
vs. ^^
1: user$eval__3138$tag__3139.invoke(NO_SOURCE_FILE:1)
^^^
Run Code Online (Sandbox Code Playgroud)
thn*_*tos 36
您还可以使用Alex Osborne的debug-repl
插入代码将自己放入包含所有本地绑定的REPL中:
(defmacro local-bindings
"Produces a map of the names of local bindings to their values."
[]
(let [symbols (map key @clojure.lang.Compiler/LOCAL_ENV)]
(zipmap (map (fn [sym] `(quote ~sym)) symbols) symbols)))
(declare *locals*)
(defn eval-with-locals
"Evals a form with given locals. The locals should be a map of symbols to
values."
[locals form]
(binding [*locals* locals]
(eval
`(let ~(vec (mapcat #(list % `(*locals* '~%)) (keys locals)))
~form))))
(defmacro debug-repl
"Starts a REPL with the local bindings available."
[]
`(clojure.main/repl
:prompt #(print "dr => ")
:eval (partial eval-with-locals (local-bindings))))
Run Code Online (Sandbox Code Playgroud)
然后使用它,将其插入到您希望repl启动的任何位置:
(defn my-function [a b c]
(let [d (some-calc)]
(debug-repl)))
Run Code Online (Sandbox Code Playgroud)
我把它粘在我的user.clj中,所以它在所有REPL会话中都可用.
Pet*_*ott 15
"使用repl调试Clojure代码的最佳方法"
稍微左侧的字段,但"使用REPL iteself".
我已经写了一年多的业余爱好者Clojure,并没有对任何调试工具感到非常需要.如果你保持你的函数很小,并在REPL中使用预期输入运行每个函数并观察结果,那么应该可以非常清楚地了解代码的行为方式.
我发现调试器对于在正在运行的应用程序中观察STATE最有用.Clojure使用不可变数据结构(没有改变状态)的函数式编写变得简单(而且有趣!).这大大减少了对调试器的需求.一旦我知道所有组件的行为与我期望的一样(特别注意事物的类型),那么大规模行为很少成为问题.
如果您使用emacs/slime/swank,请在REPL中尝试:
(defn factorial [n]
(cond (< n 2) n
(= n 23) (swank.core/break)
:else (* n (factorial (dec n)))))
(factorial 30)
Run Code Online (Sandbox Code Playgroud)
它不会像你在LISP下那样给你一个完整的堆栈跟踪,但是它很适合探索.
这是很好的工作:
http://hugoduncan.org/post/2010/swank_clojure_gets_a_break_with_the_local_environment.xhtml
正如上面的评论中提到的那样.
从2016年开始,您可以使用Debux,这是一个用于Clojure/Script的简单调试库,可与您的repl和浏览器控制台配合使用.您可以在代码中撒上dbg
(debug)或clog
(console.log)宏,并轻松观察打印到REPL和/或控制台的各个函数的结果等.
从项目的自述文件:
基本用法
这是一个简单的例子.宏dbg打印一个原始表单,并在REPL窗口上漂亮地打印评估值.然后它返回值而不会干扰代码执行.
如果用这样的dbg包装代码,
(* 2 (dbg (+ 10 20))) ; => 60
REPL窗口中将打印以下内容.
REPL输出:
dbg: (+ 10 20) => 30
嵌套的dbg
dbg宏可以嵌套.
(dbg (* 2 (dbg (+ 10 20)))) ; => 60
REPL输出:
Run Code Online (Sandbox Code Playgroud)`dbg: (+ 10 20) => 30`
dbg: (* 2 (dbg (+ 10 20))) => 60
Hugo Duncan和合作者继续为ritz项目做出惊人的工作.Ritz-nrepl是一款具有调试功能的nREPL服务器.观看Hugo的调试人员在Clojure的Clojure/Conj 2012演讲中看到它的实际效果,在视频中,一些幻灯片不可读,所以你可能想从这里查看幻灯片.