Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Clojure: How do I get the file/line number on which a map was defined?

Tags:

clojure

reader

I know I can get the :line and :file from the metadata on a var; however, I'm building a system where the user can pass me raw maps and I will end up "linking" the data together at a later time. When this linkage fails, I'd like to report the file/line in which they specified the map. E.g.:

 (defn generate-stuff []
    (make-thing { :k (make-thing { :k v }) }))

 (link (generate-stuff) (other-generator))
 ;; outputs file/line of the map containing the errant :k/v pair

I assume that writing a macro to associate file/line with the collection's metadata is almost certainly the way to go, but since there isn't any "var" to look at, I'm not sure where to get the line number. I see the definition of get-line-number, but it requires a reader, and while I can find all of the special readers and the *default-data-reader-fn* data reader (which is nil), I cannot seem to figure out how to access the "code" reader.

like image 448
Tony K. Avatar asked Oct 17 '25 11:10

Tony K.


1 Answers

OK, it looks like using &form in a macro is the answer. I wrote the following bit of generic test code, and it seems to work:

(defmacro make-thing [obj]
  (let [f *file*]
    (with-meta obj (assoc (meta &form) :file f))))

The &form refers to the form that invoked the macro, and it has metadata for line/column. The special var file has the relative path of the source file. So, combining the two into the metadata onto the object results in the desired result.

like image 128
Tony K. Avatar answered Oct 21 '25 00:10

Tony K.



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!