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


当前回答

我有一个调试宏,我觉得非常有用:

;;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)

其他回答

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

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

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

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

def-let的函数版本,它将一个let转换为一系列defs。有些功劳要归功于这里

(defn def-let [aVec]
  (if-not (even? (count aVec))
    aVec
    (let [aKey (atom "")       
          counter (atom 0)]
      (doseq [item aVec]
        (if (even? @counter) 
          (reset! aKey  item)           
          (intern *ns*  (symbol @aKey)  (eval item)))
        ;   (prn  item)       
    (swap! counter inc)))))

用法:需要用引文来引用内容。

(def-let '[a 1 b 2 c (atom 0)])

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

来自Java并且熟悉Eclipse,我喜欢逆时针(用于Clojure开发的Eclipse插件)提供的功能:http://doc.ccw-ide.org/documentation.html#_debug_clojure_code

从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