当使用repl时,调试Clojure代码的最佳方法是什么?
当前回答
使用repl调试Clojure代码的最佳方法
稍微偏左,但是“使用REPL本身”。
我写Clojure已经有一年多的时间了,并没有觉得对任何调试工具有很大的需求。如果你保持你的函数很小,并且在REPL中运行每个函数,并观察结果,那么你应该可以非常清楚地了解你的代码是如何行为的。
我发现调试器对于观察正在运行的应用程序中的STATE最有用。Clojure使使用不可变数据结构(不变状态)的函数式风格编写变得容易(而且有趣!)这大大减少了对调试器的需求。一旦我知道所有组件的行为都符合我的预期(特别注意事物的类型),那么大规模的行为就很少会成为问题。
其他回答
还有dotrace,它允许您查看所选函数的输入和输出。
(use 'clojure.contrib.trace)
(defn fib[n] (if (< n 2) n (+ (fib (- n 1)) (fib (- n 2)))))
(dotrace [fib] (fib 3))
产生输出:
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
在Clojure 1.4中,dotrace已经移动了:
你需要依赖:
[org.clojure/tools.trace "0.7.9"]
(require 'clojure.tools.trace)
您需要将^:dynamic添加到函数定义中
(defn ^:dynamic fib[n] (if (< n 2) n (+ (fib (- n 1)) (fib (- n 2)))))
那鲍勃又成了你的叔叔了
(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
你也可以插入代码,使用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))))
然后要使用它,将它插入到你想要repl开始的地方:
(defn my-function [a b c]
(let [d (some-calc)]
(debug-repl)))
我把这个插入我的用户。clj,所以在所有REPL会话中都可用。
使用repl调试Clojure代码的最佳方法
稍微偏左,但是“使用REPL本身”。
我写Clojure已经有一年多的时间了,并没有觉得对任何调试工具有很大的需求。如果你保持你的函数很小,并且在REPL中运行每个函数,并观察结果,那么你应该可以非常清楚地了解你的代码是如何行为的。
我发现调试器对于观察正在运行的应用程序中的STATE最有用。Clojure使使用不可变数据结构(不变状态)的函数式风格编写变得容易(而且有趣!)这大大减少了对调试器的需求。一旦我知道所有组件的行为都符合我的预期(特别注意事物的类型),那么大规模的行为就很少会成为问题。
使用spyscope实现一个自定义阅读器宏,这样你的调试代码也是生产代码 https://github.com/dgrnbrg/spyscope
从2016年开始,你可以使用Debux,这是Clojure/Script的一个简单调试库,可以与repl以及浏览器的控制台一起工作。您可以在代码中添加dbg (debug)或clog (console.log)宏,并轻松观察各个函数的结果,等等,打印到您的REPL和/或控制台。
来自项目的Readme:
Basic usage This is a simple example. The macro dbg prints an original form and pretty-prints the evaluated value on the REPL window. Then it returns the value without interfering with the code execution. If you wrap the code with dbg like this, (* 2 (dbg (+ 10 20))) ; => 60 the following will be printed in the REPL window. REPL output: dbg: (+ 10 20) => 30 Nested dbg The dbg macro can be nested. (dbg (* 2 (dbg (+ 10 20)))) ; => 60 REPL output: `dbg: (+ 10 20) => 30` dbg: (* 2 (dbg (+ 10 20))) => 60
推荐文章
- 如何在Visual Studio中找到堆栈跟踪?
- 有一个好的Valgrind Windows的替代品吗?
- Eclipse调试器总是阻塞在ThreadPoolExecutor上,没有任何明显的异常,为什么?
- Visual Studio:如何打破处理异常?
- 确保您的项目构建设置正在生成一个dSYM文件。对于所有配置,DEBUG_INFORMATION_FORMAT都应该设置为dwarf-with-dsym
- 如何获得GDB中所有线程的回溯?
- 如何检测IE11?
- 如何通过参数和重定向stdin从一个文件到程序运行在gdb?
- 如何在Clojure中创建web应用程序?
- 我如何调试git/git-shell相关的问题?
- Visual Studio拒绝忘记断点?
- 如何在Python自己的调试器(PDB)中执行多行语句
- 我如何在Visual Studio中预处理后看到C/ c++源文件?
- Linux有c++ gdb图形用户界面吗?
- 是什么让Visual Studio调试器停止评估ToString重写?