1
votes

If I have a namespace symbol e.g. 'clojure.core or a path to a clojure source file how can I get all symbols that are new to the namespace, i.e. not :refer-ed or interned in another namespace?

Those symbols would come from top level defs (and defns) but also inside let bindings and such. My goal is to analyze a namespace and walk the tree effectively doing a find-replace on certain symbols based on a predicate.

Edit: I'm not just looking for top level vars, I'm looking for any symbol. If there's a function with a let binding in it I'm looking for symbol that was bound.

1
You will probably want to use clojure.tools.analyzer rather than walking the tree yourself. It should be able to tell you where symbols come from as part of the tree walk anyway, so you won't need this preliminary step of gathering "new" symbols anyway.amalloy
See stackoverflow.com/a/19664649/1455243 . Your question not exactly the same as how to list functions of a namespace but dir in that answer does what you want, it appears.Mars
Not quite, dir won't get me the non-interned symbols in var scope like those in a let bindingCody Canning

1 Answers

2
votes

The comments you've received tell you how to get the top-level refs, however there's only one way to get the local let bindings, and that's to access the &env special form which is only available inside a macro:

(defmacro info []
  (println &env))

(def a 5)
(let [b a] (let [c 8] (info)))

;{ b #object[clojure.lang.Compiler$LocalBinding 0x72458346 clojure.lang.Compiler$LocalBinding@72458346],
;  c #object[clojure.lang.Compiler$LocalBinding 0x5f437195 clojure.lang.Compiler$LocalBinding@5f437195]}

To get a map of local names to local values, for example:

(defmacro inspect []
  (->> (keys &env)
       (map (fn [k] [`'~k k]))
       (into {})))

(let [b a] (let [c 8] (inspect)))
; => {b 5, c 8}