REPL-Driven Development and Debugging

37.1 The Workflow

Start a REPL connected to your editor (Calva/CIDER/Cursive).

Write a function, evaluate it with a keystroke, and call it in a rich comment block.

Inspect results inline, refine, and re-evaluate. Keep the program running.

Move stable experiments into tests.

Reloading: (require 'myapp.core :reload), tools.namespace ((refresh)), and Integrant's (reset) for system restarts (Module 41).

(defn parse-line [line]
  (let [[name age] (clojure.string/split line #",")]
    {:name name :age (parse-long age)}))

(comment
  (parse-line "Ana,30")              ; evaluate this form in the editor
  (map parse-line ["Ana,30" "Bo,25"])
  (def sample (slurp "people.csv"))
  )

37.2 Debugging Tools

Portal / Reveal / Morse: data inspectors that receive tap> values. Flowstorm: a time-travel debugger for Clojure. CIDER debugger (#dbg reader tag) and Cursive's IntelliJ debugger support breakpoints.

(println "x =" x)                    ; classic
(prn x)                              ; readable printing
(tap> {:event :debug :data x})       ; send values to tap listeners (Portal, Reveal, Morse)
(add-tap println)                    ; a simple tap listener
(clojure.pprint/pprint big-map)      ; pretty printing
(clojure.repl/pst)                   ; print the stack trace of the last exception
*e                                   ; the last exception
(clojure.main/ex-triage (Throwable->map *e))   ; categorized error info
(require '[clojure.tools.trace :refer [trace-ns deftrace]])   ; tracing