首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何查找包含特定元数据的所有var

如何查找包含特定元数据的所有var
EN

Stack Overflow用户
提问于 2013-11-06 11:31:37
回答 1查看 109关注 0票数 3

假设我在vars中添加了特定的元数据:

代码语言:javascript
复制
(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 (跨不同名称空间)。有可能吗?

这就是为什么。我的应用程序由几个模块组成,这些模块必须在启动时初始化。可以添加新模块并删除现有模块(当然不是在运行时),而且必须在不知道模块的任何细节的情况下调用它的初始化器。我想将元数据添加到初始化器中,然后查找所有元数据并调用。

我想知道是否有更好的方法。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-11-06 12:51:31

因此,如果您require包含非私有初始化器的所有名称空间,all-ns就能够检索这些名称空间的列表。如果您不知道存在什么名称空间,您可能可以使用例如tools.namespace来查找。

下面的函数查找包含特定元数据键集为true的所有var,并返回vars值的seq。

代码语言:javascript
复制
(defn find-by-var-meta
  [metadata-flag]
  (->> (all-ns)
       (mapcat ns-publics)
       (keep
         (fn [[_ v]]
           (when (-> v meta metadata-flag)
             (var-get v))))))

然后可以遍历生成的seq,并调用所有函数。所以,在您的例子中,应该是这样的:

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

在REPL中进行快速检查:

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

(如图所示,如果只想将一个键(或多个键)设置为true,也不需要为元数据指定完整的映射。)

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19810972

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档