Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Clojure: Debugging Println, __LINE_NUMBER__ and __FILE_NAME__

Tags:

clojure

Context

Currently,

(println "x is" x)

just prints out

x is 10

Now, what I want is something like this:

(my-println "x is" x)

to print out:

foo.clj:23> x is 10

Informally, I want my-println to append the _FILE_NAME_ and _LINE_NUMBER_ into my println.

Question:

I know how to use macros. However, I don't know how to extract the _FILE_NAME_ and _LINE_NUMBER_ from the current location in Clojure (whereas C macros make this trivial to do). How do I get the current FILE_NAME_ and _LINE_NUMBER_ ?

Thanks.

like image 255
user1383359 Avatar asked Jun 08 '12 23:06

user1383359


1 Answers

(defmacro my-println [x]
  `(do (printf "%s:%s> %s is %s\n"
               ~*file*
               ~(:line (meta &form))
               ~(pr-str x)
               ~x)
       (flush)))

Looking at this answer again much later, you can be a bit more clever if you like, reducing the runtime costs by interpolating the string constants at compile time:

(defmacro my-println [x]
  `(println ~(format "%s:%s> %s is"
                     *file*
                     (:line (meta &form))
                     (pr-str x))
            ~x))

As you can see from the macroexpansion, there is no longer any need to invoke relatively-expensive printf code at runtime:

(let [x 5] (macroexpand '(my-println (+ x 5))))
(clojure.core/println "foo.clj:1> (+ x 5) is" (+ x 5))
like image 181
amalloy Avatar answered Sep 19 '22 16:09

amalloy