19

次のコードがあるとします。

(defn ^ {:graph-title "Function 1"} func-1
  [バツ]
  (xで何かをする))

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

これで「関数1」が返されると思いますが、nilが返されます。これは、私が完全には理解していない次の違いに起因すると思います。

(メタ関数-1)
=> {:ns some-ns-info、:name func-1}
(メタ#'func-1)
=> {:ns some-ns-info、:name func-1、:graph-title "Function 1"}

誰かが私にこれを説明できますか?

4

4 に答える 4

35

関数 のメタfunc-1データ、Var #'func-1のメタデータ、シンボル 'func-1のメタデータがあります。Clojureリーダーマクロは、読み取り時にシンボル^にメタデータを追加します。マクロは、コンパイル時にメタデータをシンボルからVarにコピーます。defn

Clojure 1.2より前は、関数はメタデータをサポートしていませんでした。Clojure 1.2では、これらは機能し、いくつかの標準的なVarメタデータを関数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のメタデータが必要です。

于 2011-04-08T13:57:41.193 に答える
21

メタデータは、関数ではなく変数に添付されます。

したがって、グラフのタイトルを取得するには:graph-title、変数のメタからエントリを取得する必要があります。マクロはどうですか?

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

(get-graph-title func-1)
=> "Function 1"
于 2011-04-08T13:21:31.380 に答える
3

これが防弾とは言えませんが、繁栄のためにここに置きます。何らかの理由で、Fnオブジェクトのみがあり、シンボルやVarはありません。

私の知る限り、defn評価すると、のような名前のクラスが生成され(munge fn-symbol)ます。demungeこれを逆にするという関数があります。したがって、Fnオブジェクトのクラス名からシンボルを取り戻すことができ、シンボルから変数を取り戻すことができます。

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

おかしなことに、との両方でdemunge見つけることができます、そしてそれらはまったく同じことをするので、それらのいずれかがデマンジを持ち込むことを自由に要求してください:clojure.mainclojure.repl

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

警告:

前に言ったように、最初に次のことを試してください。

(meta #'some-fn)

これは適切な慣用的なメカニズムであるため、この回答で示しているものの代わりに。

于 2020-01-23T09:43:26.817 に答える
2

ソースコードのシンボルfunc-1で指定したメタデータは、def特殊形式によってfunc-1という名前の変数にコピーされます。http://clojure.org/special_formsのdefのドキュメントを参照してください

func-1それがvarにバインドされたシンボルである場所を評価すると、varの(この場合は関数オブジェクト)を取得します。http://clojure.org/varsを参照してください

関数オブジェクト自体は、シンボル/変数で手動で指定されたメタデータを自動的に受け取りません。

したがって、必要な情報は関数にまったく含まれていません。func-1これはvarにあり、値ではなくvar自体が本当に必要であることを指定する必要があります。それが(var func-1)であり、同等のショートカット#'func-1が行います。

于 2011-04-08T13:03:57.170 に答える