1

I've seen a few variations of the following code logging macro:

 (defmacro log
   "for debugging, output code and code->val to stdout, returns val"
   [code]
    `(let [c# ~code]
      (prn '~code)
      (clojure.pprint/pprint c#)
      c#))

however, I haven't seen a recursive version that wraps all macro or function forms in the code-body. Does anyone have good working implementation?

EDIT:

To clarify, take for example the following code:

 (map #(+ % 10) (range 5))

by wrapping that in a recursive-log macro:

 (r-log (map #(+ % 10) (range 5)))

the macro-expansion of that should be:

 (log (map #(log (+ % 10)) (log (range 5))))
bmillare
  • 4,183
  • 2
  • 23
  • 42
  • can you give an example of what you're looking for? I almost certainly don't know the answer, but I'm not clear on what you want that the example code doesn't provide.. – jk. Feb 09 '11 at 00:22

3 Answers3

2

a slightly different, more targeted, approach is to call a function that adds the log function to every function in the name spaces you're working on so they log them selves when they are called. this will let you see your code run without seeing all the internals of map.

clojure: adding a debug trace to every function in a namespace?

Community
  • 1
  • 1
Arthur Ulfeldt
  • 90,827
  • 27
  • 201
  • 284
  • Not to avoid answering the question directly, but this answer is most likely a better solution than what the question is asking for. – Psyllo Feb 10 '11 at 00:17
  • While that link is useful and I thank you for that, I can still see use cases for code that does what I ask for. A good example is when you are writing a relatively large chunk of code that uses core functions instead of user defined and you only want to log function returns in the chain, not all calls to those functions. – bmillare Feb 10 '11 at 03:17
  • Yeah, after looking at it again, I think it could be useful. I'll try to write something. – Psyllo Feb 10 '11 at 04:53
1

I usually use clojure.contrib.trace to tactically introduce this sort of thing, better explained here than I could:

Debugging in Clojure?

Community
  • 1
  • 1
Alex Miller
  • 69,183
  • 25
  • 122
  • 167
1

Ok, I came up with the following. I think this is what you were asking for:

Note logx is your log macro with a variable length code argument.

 (defmacro logx
   "for debugging, output code and code->val to stdout, returns val"
   [& code]
   `(let [c# ~code]
      (prn '~code)
      (clojure.pprint/pprint c#)
      c#))

 (defn add-logx-calls [code]
   (if (seq? code)
     `(logx ~@(map add-logx-calls code))
     code))

 (defmacro r-log
   [& code]
   (apply add-logx-calls code))

 (r-log (map #(+ % 10) (range 5)))

I haven't tested it on anything but the sample you gave me. If you improve it let us know.

bmillare
  • 4,183
  • 2
  • 23
  • 42
Psyllo
  • 674
  • 5
  • 8