编辑:原来我在名称空间声明中使用require
而不是:require
。使用:require
,tools.namespace会刷新日志记录命名空间,问题就会消失。然而,我仍然感到奇怪的是,表达式(eval `(var ~(symbol "A/func")))
在下面描述的情况下不起作用(即,如果下面的B不刷新)。
总结:我正在使用tools.namespace。如果我有名称空间A和B,并且在B中执行(eval `(var ~(symbol "A/func")))
和(tools.namespace/refresh)
并运行代码,则可行。但是,如果我对A进行了更改,请执行(tools.namespace/refresh)
,以便只刷新A,然后运行该表达式会出现错误:Cannot resolve var: A/func in this context
,即使存在A/func
。为什么呢?
更长的版本:
在我的项目中,我有一个使用robert-hooke的日志模块/命名空间(见下文)。我在进行更改时使用tools.namespace重新加载代码。
问题如下:当我想记录(我的日志记录当前只是打印)时,我列出了我想要记录在日志命名空间中的函数并执行(t.n/refresh)
。这样可行。但是,如果我对包含我要记录的函数的命名空间进行更改,并且在不更改日志记录命名空间的情况下执行(t.n/refresh)
,则日志记录将不再起作用(对于已刷新的函数)。一旦我对日志记录进行了更改,以便tools.namespace刷新它,它就会重新开始工作。
因此,它就像已刷新的名称空间中的变量无法正确获取其日志记录挂钩。但我不明白为什么。
下面是我的日志命名空间。我每次运行程序时都会调用add-logging-wrappers
。
如果我在(eval `(var ~(symbol "sv/register-damage")))
内添加add-logging-wrappers
,那么在刚刚刷新日志记录并且日志记录正常工作时就可以了。但是那些日志记录不起作用的时候,该表达式会导致错误Cannot resolve var: sv/register-damage in this context
。
(ns game.logging
(require [robert.hooke :as rh]
[clojure.pprint :as pp]
[game.server.core :as sv]
[game.client.core :as cl]
[game.math :as math]
(game.common [core-functions :as ccfns]
[graphics :as gfx])
(game.server [pathfinding :as pf]))
(:use [game.utils]))
(defn log-println [name type object]
(println (str (current-thread-name) " // " name " " type ":\n"
(with-out-str
(pp/pprint object)))))
(defn print-output [name f & args]
(let [result (apply f args)]
(log-println name "output" result)
result))
(defn print-input [name f & args]
(log-println name "input" args)
(apply f args))
(defn print-call [name f & args]
(println (str (current-thread-name) "//" name))
(apply f args))
(defmacro make-name-var-list [fn-list]
`[~@(for [fn fn-list]
[(str fn) `(var ~fn)])])
(defmacro defloglist [name & fns]
`(def ~name (make-name-var-list [~@fns])))
(defn add-hooks [name-vars & wrappers]
(when (seq wrappers)
(doseq [[name var] name-vars]
(rh/add-hook var (partial (first wrappers) name)))
(recur name-vars (next wrappers))))
(defn get-ns-name-vars [ns-sym]
(-> (the-ns ns-sym) (#(.name %)) ns-interns))
(defn add-hooks-to-ns [ns-sym & wrappers]
(apply add-hooks (get-ns-name-vars ns-sym) wrappers))
(defloglist log-both
sv/distribute-exp ;; <--- things to log
sv/register-damage
sv/give-exp)
(defloglist log-input)
(defloglist log-output)
(defn add-logging-wrappers []
(dorun (->> (all-ns) (map #(.name %)) (mapcat ns-interns) (map second)
(map rh/clear-hooks)))
(add-hooks log-both print-output print-input)
(add-hooks log-input print-input)
(add-hooks log-output print-output))