5

语境

目前,

(println "x is" x)

只是打印出来

x is 10

现在,我想要的是这样的:

(my-println "x is" x)

打印出来:

foo.clj:23> x is 10

非正式地,我希望 my-println 将 _FILE_NAME_ 和 _LINE_NUMBER_ 附加到我的 println 中。

问题:

我知道如何使用宏。但是,我不知道如何从 Clojure 中的当前位置提取 _FILE_NAME_ 和 _LINE_NUMBER_(而 C 宏使这变得微不足道)。如何获取当前的 FILE_NAME_ 和 _LINE_NUMBER_ ?

谢谢。

4

2 回答 2

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

稍后再看这个答案,如果愿意,您可以更聪明一点,通过在编译时插入字符串常量来降低运行时成本:

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

从宏扩展中可以看出,不再需要在运行时调用相对昂贵的 printf 代码:

(let [x 5] (macroexpand '(my-println (+ x 5))))
(clojure.core/println "foo.clj:1> (+ x 5) is" (+ x 5))
于 2012-06-09T03:18:52.750 回答
0

像log4jlogback这样的Java 日志框架提供了这种功能。您可以配置日志系统以将行号添加到日志消息中。文件名可能更难,但至少你可以在那里拥有命名空间。

您可以使用clojure.logging为日志框架提供良好的接口。

于 2012-07-15T07:21:19.520 回答