假设我在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}然后,我想查找包含它的所有vars (跨不同名称空间)。有可能吗?
这就是为什么。我的应用程序由几个模块组成,这些模块必须在启动时初始化。可以添加新模块并删除现有模块(当然不是在运行时),而且必须在不知道模块的任何细节的情况下调用它的初始化器。我想将元数据添加到初始化器中,然后查找所有元数据并调用。
我想知道是否有更好的方法。
发布于 2013-11-06 12:51:31
因此,如果您require包含非私有初始化器的所有名称空间,all-ns就能够检索这些名称空间的列表。如果您不知道存在什么名称空间,您可能可以使用例如tools.namespace来查找。
下面的函数查找包含特定元数据键集为true的所有var,并返回vars值的seq。
(defn find-by-var-meta
[metadata-flag]
(->> (all-ns)
(mapcat ns-publics)
(keep
(fn [[_ v]]
(when (-> v meta metadata-flag)
(var-get v))))))然后可以遍历生成的seq,并调用所有函数。所以,在您的例子中,应该是这样的:
(require '[my.namespace.initializers a b c])
(find-by-var-meta :run-at-startup) ;; => seq of initializers from the above ns.在REPL中进行快速检查:
(defn ^:run-at-startup add-one [x] (inc x)) ;; => #'user/add-one
((first (find-by-var-meta :run-at-startup)) 5) ;; => 6(如图所示,如果只想将一个键(或多个键)设置为true,也不需要为元数据指定完整的映射。)
https://stackoverflow.com/questions/19810972
复制相似问题