Clojure: Как получить метаданные функций?

Я пытаюсь получить метаданные всех встроенных функций Clojure.

В предыдущем вопросе Я узнал, что этого можно достичь, используя что-то вроде ^#'func_name (получить метаданные объекта var). Но мне не удалось сделать это программно, где func-name не известно заранее.

Например, попытка получить метаданные последней функции в clojure.core:

user=> (use 'clojure.contrib.ns-utils)
nil
user=> (def last-func (last (vars clojure.core)))

user=> last-func
zipmap

;The real metadata (zipmap is hardcoded)
user=> ^#'zipmap
{:ns #<Namespace clojure.core>, :name zipmap, :file "clojure/core.clj", :line 1661, :arglists ([keys vals]), :doc "Returns a map .."}

;Try to get programmatically, but get shit
user=> ^#'last-func
{:ns #<Namespace user>, :name last-func, :file "NO_SOURCE_PATH", :line 282}

Как это можно сделать? Я уже пробовал множество вариаций, но ничего не делает трюк.

Ответ 1

Вы ищете meta и ns-resolve.

user=> (let [fun "map"] (meta (ns-resolve 'clojure.core (symbol fun))))
{:ns #<Namespace clojure.core>, :name map, :file "clojure/core.clj", :line 1705, :arglists ([f coll] [f c1 c2] [f c1 c2 c3] [f c1 c2 c3 & colls]), :doc "Returns a lazy sequence consisting of the result of applying f to the\n  set of first i tems of each coll, followed by applying f to the set\n  of second items in each coll, until any one of the colls is\n  exhausted.  Any remaining items in other colls are ignored. Function\n  f should accept number-of-colls arguments."}

Ответ 2

Технически функции не могут иметь метаданные в Clojure в настоящее время:

http://www.assembla.com/spaces/clojure/tickets/94-GC--Issue-90---%09-Support-metadata-on-fns

Однако вары, связанные с функциями, могут, и похоже, что вы находите с ns-разрешением. (meta last-func) тоже будет работать. Поскольку last-func - это сам var, ^ # 'last-func (который является сокращением для (meta (var (quote last-func)))) имеет избыточное разграничение var.