当使用repl时,调试Clojure代码的最佳方法是什么?
当前回答
使用spyscope实现一个自定义阅读器宏,这样你的调试代码也是生产代码 https://github.com/dgrnbrg/spyscope
其他回答
我有一个调试宏,我觉得非常有用:
;;debugging parts of expressions
(defmacro dbg[x] `(let [x# ~x] (println "dbg:" '~x "=" x#) x#))
你可以把它插入到任何你想看发生了什么和什么时候:
;; 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)
如果你使用emacs/slime/swank,那么在REPL试试这个:
(defn factorial [n]
(cond (< n 2) n
(= n 23) (swank.core/break)
:else (* n (factorial (dec n)))))
(factorial 30)
它不像在LISP下那样为您提供完整的堆栈跟踪,但它很适合进行探查 周围。
这是优秀的工作:
http://hugoduncan.org/post/2010/swank_clojure_gets_a_break_with_the_local_environment.xhtml
正如上面的评论所提到的。
使用repl调试Clojure代码的最佳方法
稍微偏左,但是“使用REPL本身”。
我写Clojure已经有一年多的时间了,并没有觉得对任何调试工具有很大的需求。如果你保持你的函数很小,并且在REPL中运行每个函数,并观察结果,那么你应该可以非常清楚地了解你的代码是如何行为的。
我发现调试器对于观察正在运行的应用程序中的STATE最有用。Clojure使使用不可变数据结构(不变状态)的函数式风格编写变得容易(而且有趣!)这大大减少了对调试器的需求。一旦我知道所有组件的行为都符合我的预期(特别注意事物的类型),那么大规模的行为就很少会成为问题。
我最喜欢的方法是在整个代码中自由地散布printlns。多亏了#_ reader宏,打开和关闭它们很容易(它使阅读器以下面的形式阅读,然后假装从未见过它)。或者你可以使用宏扩展为传入体或nil,这取决于一些特殊变量的值,例如*debug*:
(defmacro debug-do [& body]
(when *debug*
`(do ~@body)))
这里有一个(def *debug* false),它将扩展为nil。如果是真的,它就会扩张到裹着do的身体。
对这个SO问题的公认答案:用于进度报告的Idiomatic Clojure ?在调试序列操作时非常有用。
Then there's something which is currently incompatible with swank-clojure's REPL, but is too good not to mention: debug-repl. You can use it in a standalone REPL, which is easy to get e.g. with Leiningen (lein repl); and if you're launching your programme from the command line, then it's going to bring its own REPL up right in your terminal. The idea is that you can drop the debug-repl macro in anywhere you like and have it bring up its own REPL when the programme's execution reaches that point, with all locals in scope etc. A couple of relevant links: The Clojure debug-repl, Clojure debug-repl tricks, how 'bout a debug-repl (on the Clojure Google group), debug-repl on Clojars.
swank-clojure在使SLIME的内置调试器在处理Clojure代码时发挥了足够的作用——注意stacktrace中不相关的部分是如何被灰色化的,因此很容易找到正在调试的代码中的实际问题。需要记住的一件事是,没有“名称标签”的匿名函数出现在堆栈跟踪中,基本上没有附加任何有用的信息;当添加“name标签”时,它确实会出现在stacktrace中,并且一切正常:
(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)
^^^
Hugo Duncan和他的合作者继续在ritz项目上做着惊人的工作。Ritz-nrepl是一个具有调试功能的nREPL服务器。在Clojure/Conj 2012上观看Hugo's Debuggers in Clojure talk来查看它的实际操作,在视频中一些幻灯片是不可读的,所以你可能想从这里查看幻灯片。
推荐文章
- Python内存泄漏
- 使用Visual Studio调试器在值更改时中断
- 如何调试一个GLSL着色器?
- 漂亮地打印Java集合(toString不返回漂亮输出)
- 确定导致分段错误的代码行?
- 如何在GDB中打印c++向量的元素?
- 在Clojure中调试?
- 为什么Android工作室说“等待调试器”如果我不调试?
- 没有找到用于调试模式的此可执行文件的有效配置文件
- Visual Studio c++和Windows中的调试内存填充模式是什么?
- 为什么这个for循环在某些平台上退出,而在其他平台上不退出?
- 如何使gdb保存命令历史?
- 如何检查Flutter应用程序是否正在调试中运行?
- 如何设置断点在内联Javascript在谷歌Chrome?
- Chrome调试-打破下一个点击事件