如何在Clojure中跟踪代码执行?

时间:2017-01-30 22:44:41

标签: debugging clojure

为什么要学习Clojure,我有时需要看看每个步骤的功能是什么。例如:

(defn kadane [coll]
   (let [pos+ (fn [sum x] (if (neg? sum) x (+ sum x)))
         ending-heres (reductions pos+ 0 coll)]
     (reduce max ending-heres)))

我应该在这里和那里(在哪里,如何)插入println;或者是否有建议的工作流程/工具?

4 个答案:

答案 0 :(得分:10)

这可能不是你在单一功能级别上所追求的(参见下面的Charles Duffy的评论),但如果你想了解一下命名空间(或几个)级别的内容,你可以使用tools.trace(披露:我是贡献者):

(ns foo.core)

(defn foo [x] x)
(defn bar [x] (foo x))

(in-ns 'user) ; standard REPL namespace

(require '[clojure.tools.trace :as trace])
(trace/trace-ns 'foo.core)

(foo.core/bar 123)
TRACE t20387: (foo.core/bar 123)
TRACE t20388: | (foo.core/foo 123)
TRACE t20388: | => 123
TRACE t20387: => 123

它不会捕获内部函数等(正如Charles所指出的那样),并且可能会对大型代码图表产生压力,但在探索小型代码图时,它可能非常方便。

(如果感兴趣的组与名称空间不完全对齐,也可以跟踪单独选择的Vars。)

答案 1 :(得分:6)

Sayid是Clojure Conj 2016上展示的工具,它直接适用于此目的,并附带一个优秀的Emacs插件。请参阅the talk at which it was presented

要查看瞬态函数的内部调用,请参阅ws-add-inner-trace-fn(之前为ws-add-deep-trace-fn)。

答案 2 :(得分:4)

出于此目的,我经常使用来自the Tupelo libraryspyx和相关函数,例如spy-let

(ns tst.clj.core
  (:require [tupelo.core :as t] ))
(t/refer-tupelo)

(defn kadane [coll]
   (spy-let [ pos+ (fn [sum x] (if (neg? sum) x (+ sum x)))
              ending-heres (reductions pos+ 0 coll) ]
     (spyx (reduce max ending-heres))))
(spyx (kadane (range 5)))

将产生输出:

pos+ => #object[tst.clj.core$kadane$pos_PLUS___21786 0x3e7de165 ...]
ending-heres => (0 0 1 3 6 10)
(reduce max ending-heres) => 10
(kadane (range 5)) => 10

恕我直言,很难打败一个简单的println或类似的调试。随着您接近生产,日志文件也非常宝贵。

答案 3 :(得分:4)

如果您像大多数Clojurians一样使用带有CIDER的Emacs,那么您已经有了内置的调试器:

https://github.com/clojure-emacs/cider/blob/master/doc/debugging.md

很可能是您最喜欢的IDE /编辑器内置了一些内容或者已经有插件。

还有(没有特别的顺序):

我先看看上面的内容。然而,还有其他可能性:

此外,如果函数足够简单,您可以在开发时添加def以在函数内的给定时间内查看绑定内部。