如何动态查找Clojure函数的元数据?

时间:2022-03-30 22:47:02

Say I have the following code:

说我有以下代码:

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

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

I expect this to return "Function 1", but it returns nil. I think this stems from the following difference, which I don't totally comprehend:

我希望这会返回“Function 1”,但它返回nil。我认为这源于以下差异,我不完全理解:

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

Can someone explain this to me?

谁可以给我解释一下这个?

3 个解决方案

#1


18  

The metadata is attached to the var, not to the function.

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

Thus, to get the graph title, you have to get the entry :graph-title from the meta of the var. How do you like your macros ?

因此,要获得图形标题,您必须从var的元数据中获取条目:graph-title。你觉得你的宏怎么样?

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

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

#2


30  

There's metadata on the function func-1, metadata on the Var #'func-1, and metadata on the symbol 'func-1. The Clojure reader macro ^ adds metadata to the symbol, at read time. The defn macro copies metadata from the symbol to the Var, at compile time.

关于函数func-1的元数据,Var#'func-1上的元数据以及符号'func-1上的元数据。 Clojure读取器宏^在读取时将元数据添加到符号。 defn宏在编译时将元数据从符号复制到Var。

Prior to Clojure 1.2, functions did not support metadata. In Clojure 1.2, they do, and defn also copies some standard Var metadata to the function:

在Clojure 1.2之前,函数不支持元数据。在Clojure 1.2中,他们这样做,并且defn还将一些标准Var元数据复制到该函数:

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, ...

However, in current Clojure 1.3 snapshots, defn does not copy any metadata to the function:

但是,在当前的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, ...

In general, if you want to get at the metadata of a definition, you want metadata on the Var.

通常,如果要获取定义的元数据,则需要Var上的元数据。

#3


2  

The metadata you specify on the symbol func-1 in your source code is copied to the var named func-1 by the def special form. See the documentation for def in http://clojure.org/special_forms

您在源代码中的符号func-1上指定的元数据将通过def特殊形式复制到名为func-1的var中。请参阅http://clojure.org/special_forms中的def文档

When you evaluate func-1 where that's a symbol bound to a var, you get the value of the var (which is the function object in this case). See http://clojure.org/vars

当你评估func-1这是一个绑定到var的符号时,你得到var的值(在这种情况下是函数对象)。见http://clojure.org/vars

The function object itself does not automatically recieve the metadata manually specified on the symbol / var.

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

So, the information you want is not in the function at all. It's in the var, and you have to specify that you really want the var func-1 itself instead of its value. That's what (var func-1), and the equivalent short-cut #'func-1 does.

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

#1


18  

The metadata is attached to the var, not to the function.

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

Thus, to get the graph title, you have to get the entry :graph-title from the meta of the var. How do you like your macros ?

因此,要获得图形标题,您必须从var的元数据中获取条目:graph-title。你觉得你的宏怎么样?

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

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

#2


30  

There's metadata on the function func-1, metadata on the Var #'func-1, and metadata on the symbol 'func-1. The Clojure reader macro ^ adds metadata to the symbol, at read time. The defn macro copies metadata from the symbol to the Var, at compile time.

关于函数func-1的元数据,Var#'func-1上的元数据以及符号'func-1上的元数据。 Clojure读取器宏^在读取时将元数据添加到符号。 defn宏在编译时将元数据从符号复制到Var。

Prior to Clojure 1.2, functions did not support metadata. In Clojure 1.2, they do, and defn also copies some standard Var metadata to the function:

在Clojure 1.2之前,函数不支持元数据。在Clojure 1.2中,他们这样做,并且defn还将一些标准Var元数据复制到该函数:

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, ...

However, in current Clojure 1.3 snapshots, defn does not copy any metadata to the function:

但是,在当前的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, ...

In general, if you want to get at the metadata of a definition, you want metadata on the Var.

通常,如果要获取定义的元数据,则需要Var上的元数据。

#3


2  

The metadata you specify on the symbol func-1 in your source code is copied to the var named func-1 by the def special form. See the documentation for def in http://clojure.org/special_forms

您在源代码中的符号func-1上指定的元数据将通过def特殊形式复制到名为func-1的var中。请参阅http://clojure.org/special_forms中的def文档

When you evaluate func-1 where that's a symbol bound to a var, you get the value of the var (which is the function object in this case). See http://clojure.org/vars

当你评估func-1这是一个绑定到var的符号时,你得到var的值(在这种情况下是函数对象)。见http://clojure.org/vars

The function object itself does not automatically recieve the metadata manually specified on the symbol / var.

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

So, the information you want is not in the function at all. It's in the var, and you have to specify that you really want the var func-1 itself instead of its value. That's what (var func-1), and the equivalent short-cut #'func-1 does.

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