EDIT: It turned out that I used requireinstead :requirein the namespace declaration. C :require, tools.namespace updates the log namespace and the problem goes away. However, I'm still curious that the expression (eval `(var ~(symbol "A/func")))does not work in the situation described below (that is, if B is not updated below).
Summary: I use tools.namespace. If I have the spaces A and B names and B do (eval `(var ~(symbol "A/func")))and (tools.namespace/refresh)and code execution, it works. But if I made changes to A, make (tools.namespace/refresh)it so that only A is updated, and then running this expression, you will get an error: Cannot resolve var: A/func in this contextalthough it A/funcexists. Why?
Longer version:
In my project, I have a registration module / namespace that uses robert-hooke (see below). I use tools.namespace to reload my code when making changes.
The problem is this: when I want the journal (my journal is currently just printing) something, I list the functions that I want to register in my journal namespace and do it (t.n/refresh). It works. But if I make changes to the namespaces that contain the functions that I want to register and do (t.n/refresh)without making changes to the log namespace, the log no longer works (for updated functions). As soon as I make changes to the log, so that it is also updated using tools.namespace, it starts working again.
, , vars , , . , .
. 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))