动态检索Clojure函数元数据

G S*_*ton 8 metadata function clojure defn

环境:Clojure 1.4

我试图从函数向量中动态提取函数元数据.

(defn #^{:tau-or-pi: :pi} funca "doc for func a" {:ans 42} [x] (* x x))
(defn #^{:tau-or-pi: :tau} funcb "doc for func b" {:ans 43} [x] (* x x x))

(def funcs [funca funcb])
Run Code Online (Sandbox Code Playgroud)

现在,检索REPL中的元数据(有点)是直截了当的:

user=>(:tau-or-pi (meta #'funca))
:pi

user=>(:ans (meta #'funca))
42

user=>(:tau-or-pi (meta #'funcb))
:tau

user=>(:ans (meta #'funcb))
43
Run Code Online (Sandbox Code Playgroud)

然而,当我尝试做一个地图,让:ans,:tau-or-pi或基本:name从元数据,我得到异常:

user=>(map #(meta #'%) funcs)
CompilerException java.lang.RuntimeException: Unable to resolve var: p1__1637# in this context, compiling:(NO_SOURCE_PATH:1) 
Run Code Online (Sandbox Code Playgroud)

在做了一些搜索后,我从2009年的帖子中得到了以下想法(https://groups.google.com/forum/?fromgroups=#!topic/clojure/VyDM0YAzF4o):

user=>(map #(meta (resolve %)) funcs)
ClassCastException user$funca cannot be cast to clojure.lang.Symbol  clojure.core/ns-resolve (core.clj:3883)
Run Code Online (Sandbox Code Playgroud)

我知道defn宏(在Clojure 1.4中)将元数据放在宏Vardef部分中,defn这就是简单(meta #'funca)工作的原因,但有没有办法动态获取函数元数据(map如上例所示)?

也许我在语法上遗漏了一些东西,但如果有人能指出我正确的方向或正确的方法,那就太好了.

谢谢.

Bey*_*mor 2

最近,我发现将元数据附加到函数本身而不是变量上很有用defn

你可以用 good ol' 来做到这一点def

(def funca ^{:tau-or-pi :pi} (fn [x] (* x x)))
(def funcb ^{:tau-or-pi :tau} (fn [x] (* x x x)))
Run Code Online (Sandbox Code Playgroud)

在这里,元数据已附加到函数,然后将那些包含元数据的函数绑定到变量。

这样做的好处是,在考虑元数据时您不再需要担心变量。由于这些函数包含元数据,因此您可以直接从它们中提取元数据。

(def funcs [funca funcb])

(map (comp :tau-or-pi meta) funcs) ; [:pi :tau]
Run Code Online (Sandbox Code Playgroud)

显然, 的语法def并不像defn函数那样精致,因此根据您的使用情况,您可能有兴趣重新实现defn以将元数据附加到函数。