代码之家  ›  专栏  ›  技术社区  ›  Arthur Ulfeldt

clojure:向名称空间中的每个函数添加调试跟踪吗?

  •  17
  • Arthur Ulfeldt  · 技术社区  · 14 年前

    刚开始在我的一个家庭项目中使用log4j,我正要拿出鼠标并剪切粘贴 (trace (str "entering: " function-name)) 到一个大模块中的每个函数中。然后理性的声音追上来说,“只有更好的方法了”…我可以考虑制作一个宏来包装一整块函数并向它们添加跟踪,或者类似的东西?智者的建议有没有满溢的Clojurians?

    1 回复  |  直到 14 年前
        1
  •  17
  •   Michał Marczyk    14 年前

    不需要宏:

    (defn trace-ns
      "ns should be a namespace object or a symbol."
      [ns]
      (doseq [s (keys (ns-interns ns))
              :let [v (ns-resolve ns s)]
              :when (and (ifn? @v) (-> v meta :macro not))]
        (intern ns
                (with-meta s {:traced true :untraced @v})
                (let [f @v] (fn [& args]
                              (clojure.contrib.trace/trace (str "entering: " s))
                              (apply f args))))))
    
    (defn untrace-ns [ns]
      (doseq [s (keys (ns-interns ns))
              :let [v (ns-resolve ns s)]
              :when (:traced (meta v))]
        (alter-meta! (intern ns s (:untraced (meta v)))
                     #(dissoc % :traced :untraced))))
    

    …或者类似的东西。最可能的额外要求是使用 filter 为了不打电话 trace 关于那些不属于 ifn? S. 更新:在解决方案中编辑(也处理宏)。更新2:修正了一些主要的错误。更新4:添加了取消跟踪功能。

    更新3: 以下是我的回复示例:

    user> (ns foo)
    nil
    foo> (defn foo [x] x)
    #'foo/foo
    foo> (defmacro bar [x] x)
    #'foo/bar
    foo> (ns user)
    nil
    user> (trace-ns 'foo)
    nil
    user> (foo/foo :foo)
    TRACE: "entering: foo"
    :foo
    user> (foo/bar :foo)
    :foo
    user> (untrace-ns 'foo)
    nil
    user> (foo/foo :foo)
    :foo