I'm still learning clojure and wrote this decidedly unfunctional bit of code as part of a common lisp style DESCRIBE function.
nor did I think it would make the code shorter (correct me if I'm wrong).
Anyway, with regard to mutable state is there a more concise and/or preferred way to do this?
The function in question is just querying the many maps of a namespace to yield another map with some interpretations of the namespace with respect to a given symbol. I am struggling with some of the capabilities of namespaces and so this was just a bit of learning code for me, though I have to say my resulting DESCRIBE function has been really useful to me. At some point when it's not a total embarrassment perhaps I'll post it.
(defn ns-symbol-relationship
"Return a map of entries that describe the relationship of a symbol to a given namespace."
[ns symbol]
(if (not (symbol? symbol))
(throw (Exception. (str "ns-symbol-relationship expected symbol, got " symbol))))
;; ns-name ns-aliases ns-imports ns-interns ns-map ns-publics ns-refers
(with-local-vars [result (transient {})]
(when (= (ns-name ns) symbol) ;ns-name gives a symbol
(var-set result (assoc! (var-get result) :names-ns ns))) ;symbol names namespace
; ns-aliases gives a map, but the k/v types/semantics are presently unknown
(doseq [[k v] (seq (ns-aliases ns))]
(when (= k symbol)
(var-set result (assoc! (var-get result) :alias-for v)))
(when (= v symbol)
(var-set result (assoc! (var-get result) :aliased-by k))))
;; ns-imports keyed by symbol, valued by class
(if-let [v (get (ns-imports ns) symbol)]
(var-set result (assoc! (var-get result) :imports v))) ;symbol names imported class
;; ns-interns gives a map, keys are symbols in the namespace, values are vars( and special forms?)
;; that they map to.
(if-let [v (get (ns-interns ns) symbol)]
(var-set result (assoc! (var-get result) :interns v)))
;; ns-maps gives a map, value types/semantics are unknown
(if-let [v (get (ns-map ns) symbol)]
(var-set result (assoc! (var-get result) :maps-to v)))
;; ns-publics gives a map of public intern mappings, presumably a subset of ns-interns
(if-let [v (get (ns-publics ns) symbol)]
(var-set result (assoc! (var-get result) :interns-publicly v)))
;; ns-refers gives a map of refer-mappings, value semantics unknown
(if-let [v (get (ns-refers ns) symbol)]
(var-set result (assoc! (var-get result) :refers-to v)))
(persistent! (var-get result))))