7

My current method: if there's a function that I know has an bug, I copy bits and pieces of it into the REPL and evaluate to see if the output is what I expect. To set it up, I have to def the arguments to the function as dummy input. Not terribly time-consuming, but I know there's a more efficient way.

Any suggestions?

yayitswei
  • 4,587
  • 5
  • 27
  • 34
  • 4
    Just found, and learned a lot from, this related question: http://stackoverflow.com/questions/2352020/debugging-in-clojure, but if anyone has thoughts with respect to my specific case (debugging the output of a (purely functional) function) I would "accept" your good ideas! Thanks – yayitswei Sep 25 '10 at 02:45
  • +1 because I wish I knew anything about Lisp-related languages – JAL Sep 25 '10 at 02:45
  • I'm still learning the basics, but if I were to need to leap ahead to debugging an actual script/module, I would check out a unit testing package: `clojure.contrib.test-is` is one; IIRC there are one or two others. – intuited Sep 25 '10 at 02:58

5 Answers5

4

Does this macro help? It turns a let into a series of defs, so that you can evaluate the subexpressions:

(defmacro def-let
  "like let, but binds the expressions globally."
  [bindings & more]
  (let [let-expr (macroexpand `(let ~bindings))
        names-values (partition 2 (second let-expr))
        defs   (map #(cons 'def %) names-values)]
    (concat (list 'do) defs more)))

I wrote an explanation here: http://www.learningclojure.com/2010/09/astonishing-macro-of-narayan-singhal.html

John Lawrence Aspden
  • 17,124
  • 11
  • 67
  • 110
2

After reading up on this, my new favorite method is to add

(swank.core/break)

inside the function and inspect values by pressing 't'. (I'm using swank-clojure)

Source: http://hugoduncan.org/post/2010/swank_clojure_gets_a_break_with_the_local_environment.xhtml

yayitswei
  • 4,587
  • 5
  • 27
  • 34
1

Function version of def-let, some credit goes to here.

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

Usage: Needs to quote the content with a quotation, e.g.

(def-let '[a 1 b 2 c (atom 0)])
Community
  • 1
  • 1
Kevin Zhu
  • 2,746
  • 26
  • 23
1

for bugs spanning several functions I like the Trace macro for reporting the calls and returns of each function.

Arthur Ulfeldt
  • 90,827
  • 27
  • 201
  • 284
1

I wrote an tracing library which can show you what value every element returned.
http://github.com/hozumi/eyewrap

Takahiro Hozumi
  • 701
  • 5
  • 11
  • How does this compare with the `dotrace` macro in `clojure.contrib.trace`? They seem to have similar goals/functionality. – intuited Sep 28 '10 at 21:30
  • Difference is subtle. dotrace can trace specified function deeply in every function which target function calls. eyewrap traces all elements in target function and shows you shallow results. – Takahiro Hozumi Sep 29 '10 at 15:51