Reputation: 2753
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.
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.
Upvotes: 5
Views: 1176
Reputation: 91857
(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))
Upvotes: 10
Reputation: 34271
Java logging frameworks like log4j and logback provide this kind of functionality. You can configure logging system to add the line numbers to log messages. File name may be more difficult, but at least you can have the namespace there.
You can use clojure.logging to provide nice interface to the logging frameworks.
Upvotes: 0