Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to lookup all vars containing specific metadata

Suppose I've added specific metadata to my vars:

(defn ^:run-at-startup init []
  (prn "Initializing...")
  :done)

(meta (var init))
; {:arglists ([]), :ns #<Namespace user>, :name init, :end-column 34, 
; :run-at-startup true, :column 1, :line 5, :file "NO_SOURCE_FILE", :end-line 5}

Then I would like to lookup all the vars (across different namespaces) that contains it. Is it possible?

Here is why. My app consists of several modules that must be initialized at startup. New modules could be added and existing removed (not at runtime, of course), and it's initializers must be called without knowing any specifics of the module. I think of adding metadata to initializers, then looking it all up and calling.

I would like to know if there are better ways.

like image 465
lambdas Avatar asked Jan 17 '26 00:01

lambdas


1 Answers

So, if you require all the namespaces that contain your non-private initializers, all-ns is able to retrieve a list of those namespaces. If you do not know what namespaces exist, you can probably use e.g. tools.namespace to find out.

The following function finds all vars that contain a certain metadata key set to true, returning a seq of the vars' values.

(defn find-by-var-meta
  [metadata-flag]
  (->> (all-ns)
       (mapcat ns-publics)
       (keep
         (fn [[_ v]]
           (when (-> v meta metadata-flag)
             (var-get v))))))

The resulting seq can then be traversed and everything that is a function can be called. So, in your case this should look like this:

(require '[my.namespace.initializers a b c])
(find-by-var-meta :run-at-startup) ;; => seq of initializers from the above ns.

And a quick check in the REPL:

(defn ^:run-at-startup add-one [x] (inc x))    ;; => #'user/add-one
((first (find-by-var-meta :run-at-startup)) 5) ;; => 6

(As seen here, you also don't need to specify a full map for metadata if you only want to set a key - or multiple ones - to true.)

like image 143
xsc Avatar answered Jan 19 '26 18:01

xsc