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

问题描述 投票:17回答:4

说我有以下代码:

(defn ^ {:graph-title“ Function 1”} func-1[X](用x做某事)(defn get-graph-title[功能](str((元功能):图标题)))

我希望它返回“功能1”,但它返回nil。我认为这是由以下差异引起的,我并不完全理解:

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

有人可以向我解释吗?

function clojure metadata clojure-contrib
4个回答
19
投票

元数据附加到变量,而不附加到函数。

因此,要获取图形标题,您必须从var的元数据中获取条目:graph-title。您如何看待您的宏?

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

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

32
投票

[ func-1上有元数据,Var #'func-1上有元数据,符号 'func-1上有元数据。 Clojure阅读器宏^在读取时将元数据添加到symboldefn宏在编译时将元数据从symbol复制到Var

在Clojure 1.2之前,功能不支持元数据。在Clojure 1.2中,它们起作用,并且defn还将一些标准

Var

元数据复制到functionClojure 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

上。

2
投票
您在源代码的

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

当评估func-1时,这是绑定到var的符号,则得到var的

value

(在这种情况下为函数对象)。参见http://clojure.org/vars功能对象本身不会自动接收在符号/变量上手动指定的元数据。

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


0
投票
虽然我不会说这是防弹的,但为了繁荣起见,我将其放在此处,以防万一出于某种原因,您只有Fn对象,而没有符号或Var。

据我所知,当defn求值时,它将生成一个名称与(munge fn-symbol)相同的类。有一个称为demunge的函数将为我们反向执行此操作。因此,从Fn对象的类名中,我们可以找到符号,从符号中,我们可以找到var。

(-> (class some-fn) (print-str) (demunge) (symbol) (find-var) (meta) (:doc))

非常有趣的是,demungeclojure.main中都可以找到clojure.repl,它们的作用完全相同,因此可以随意要求其中的任何一个进行入库:

(require '[clojure.main :refer (demunge)]) ;; or (require '[clojure.repl :refer (demunge)])

© www.soinside.com 2019 - 2024. All rights reserved.