2017-01-30 7 views
2

Зачем изучать 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 здесь и там (где, как); или есть предлагаемый рабочий процесс/инструмент?

+2

Кстати, автоматическая трассировка и маркировка кода Clojure со значениями его переменных во время выполнения - одна из вещей, которые [редактор Light Table] (http://lighttable.com/), для всех своих сломанных обещаний , приводит к таблице. –

+0

Я просто запустил отладчик IntelliJ и установил точки останова. Прекрасно работает для меня. – Carcigenicate

ответ

8

Возможно, это не то, что вам нужно на уровне одной функции (см. Комментарий Чарльза Даффи ниже), но если вы хотите получить обзор того, что происходит на уровне пространства имен (или нескольких), вы можете использовать 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 

Это не поймает внутренние функции и такие (как указал Чарльз), и может быть подавляющим с большими кодовыми графиками, но при изучении небольших графиков кода это может быть весьма удобно.

(Это также можно проследить индивидуально подобранные Vars, если группы интересов не идеально выровнены с пространствами имен.)

+0

Я бы предложил это сам, но когда я прочитал это, OP пытается увидеть внутри одного вызова функции, нет? –

+1

(«внутри одного вызова функции» означает не только его аргументы и возвращаемые значения, но и те анонимные функции, которые он содержит). –

+0

@CharlesDuffy О, действительно, я думаю, что ты прав. +1 к Саиду. Благодаря! –

6

Sayid - это инструмент, представленный на Clojure Conj 2016, который непосредственно подходит для этой цели и поставляется с отличным плагином Emacs. См. the talk at which it was presented.

Чтобы просмотреть внутренние вызовы переходных функций, см. ws-add-inner-trace-fn (ранее, ws-add-deep-trace-fn).

+1

Автор саида. Я просто хотел оставить записку, чтобы побудить кого-нибудь, пытающегося сказать саид, войти в контакт (вопросы github, электронная почта, твиттер) с любыми вопросами или проблемами, с которыми они столкнулись. спасибо –

4

Я часто использовать spyx и связанные с ними функции, как spy-let из the Tupelo library для этой цели:

(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 или аналогичный для отладки. Файлы журналов также неоценимы по мере приближения к производству.

2

Если вы используете Emacs с сидр, как это делают большинство Clojurians, у вас уже есть встроенный отладчик :

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

Скорее всего, ваш любимый IDE/редактор имеет что-то встроенный или плагин уже.

Существует также (в произвольном порядке):

Я бы посмотрел выше.Однако там были/есть другие возможности:

Кроме того, если функция достаточно просто вы можете добавить def s во время разработки, чтобы заглянуть внутрь привязки в заданное время внутри вашей функции.

 Смежные вопросы

  • Нет связанных вопросов^_^