当使用repl时,调试Clojure代码的最佳方法是什么?


当前回答

从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

其他回答

使用repl调试Clojure代码的最佳方法

稍微偏左,但是“使用REPL本身”。

我写Clojure已经有一年多的时间了,并没有觉得对任何调试工具有很大的需求。如果你保持你的函数很小,并且在REPL中运行每个函数,并观察结果,那么你应该可以非常清楚地了解你的代码是如何行为的。

我发现调试器对于观察正在运行的应用程序中的STATE最有用。Clojure使使用不可变数据结构(不变状态)的函数式风格编写变得容易(而且有趣!)这大大减少了对调试器的需求。一旦我知道所有组件的行为都符合我的预期(特别注意事物的类型),那么大规模的行为就很少会成为问题。

下面是一个调试复杂let表单的宏:

(defmacro def+
  "def with binding (def+ [{:keys [a b d]} {:a 1 :b 2 :d 3}])"
  [bindings]
  (let [let-expr (macroexpand `(let ~bindings))
        vars (filter #(not (.contains (str %) "__"))
               (map first (partition 2 (second let-expr))))
        def-vars (map (fn [v] `(def ~v ~v)) vars)]
    (concat let-expr def-vars)))

...以及一篇解释其用途的文章。

对于IntelliJ,有一个优秀的Clojure插件叫做Cursive。除此之外,它提供了一个REPL,你可以在调试模式下运行,并步进你的Clojure代码,就像你会在例如Java。

我同意Peter Westmacott的回答,根据我的经验,在REPL中运行我的代码片断,大多数时候是一种足够的调试形式。

Emacs的CIDER有一个源调试器,您可以在Emacs缓冲区中逐步执行表达式,甚至可以注入新值。你可以在这里读到所有的信息。演示截图:

从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