2011-04-08 25 views
15

说我有下面的代码:如何动态查找Clojure函数的元数据?

 
(defn ^{:graph-title "Function 1"} func-1 
    [x] 
    (do-something-with x)) 

(defn get-graph-title 
    [func] 
    (str 
    ((meta func) :graph-title))) 

我预计这将返回“功能1”,但它返回零。我想从下面的差异,我不完全理解这源于:

 
(meta func-1) 
=> {:ns some-ns-info, :name func-1} 
(meta #'func-1) 
=> {:ns some-ns-info, :name func-1, :graph-title "Function 1"} 

有人可以解释这样对我?

回答

18

元数据附加到var,而不是函数。

因此,要获得图表标题,您必须从var的meta获得条目:graph-title。你喜欢你的宏吗?

(defmacro get-graph-title 
    [func] 
    `(:graph-title (meta (var ~func)))) 

(get-graph-title func-1) 
=> "Function 1" 
+4

或者只是使用当前的定义和做(get-graph-title#'func-1) – 2011-04-08 13:22:52

2

您在源代码中符号 FUNC-1中指定的元数据被复制到VAR由DEF特殊形式命名为FUNC-1。见http://clojure.org/special_forms

当你评估func-1哪里这是绑定到一个变种一个符号DEF文件,你得到的VAR的(在这种情况下,函数对象)。请参阅http://clojure.org/vars

函数对象本身不会自动接收在符号/ var上手动指定的元数据。

所以,你想要的信息根本不在函数中。它在var中,你必须指定你真的想要var func-1本身,而不是它的值。这就是(var func-1)和等效的快捷方式#'func-1所做的。

30

有元数据的功能func-1,在瓦尔#'func-1元数据和元数据的符号'func-1。 Clojure阅读器宏^在读取时将元数据添加到符号。在编译时,defn宏将元数据从符号复制到Var

在Clojure 1.2之前,函数不支持元数据。在Clojure的1.2,他们这样做,并defn还复制了一些标准瓦尔元至功能

Clojure 1.2.0 
user=> (defn ^{:foo :bar} func-1 [] nil) 
#'user/func-1 
user=> (meta func-1) 
{:ns #<Namespace user>, :name func-1} 
user=> (meta #'func-1) 
{:foo :bar, :ns #<Namespace user>, :name func-1, ... 

然而,在当前的Clojure 1.3快照,defn没有任何元数据复制到功能:

Clojure 1.3.0-master-SNAPSHOT 
user=> (defn ^{:foo :bar} func-1 [] nil) 
#'user/func-1 
user=> (meta func-1) 
nil 
user=> (meta #'func-1) 
{:foo :bar, :ns #<Namespace user>, :name func-1, ... 

一般来说,如果您想获取定义的元数据,您需要Var上的元数据。

+0

莱昂内尔的答案更接近我所寻找的,但感谢解释 - 清理了很多东西。 – funkymunky 2011-04-10 06:16:42