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

青春壹個敷衍的年華 提交于 2019-12-10 10:46:52

问题


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.


回答1:


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.



来源:https://stackoverflow.com/questions/30812123/clojure-how-do-i-get-the-file-line-number-on-which-a-map-was-defined

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!