【发布时间】:2014-06-01 06:12:42
【问题描述】:
我正在尝试读取 Clojure 中函数集合的元数据,但 var 或 reader 特殊形式不起作用,除非它们直接处理符号。
; this works
(var my-fn)
; this doesn't
(defn val-it [x] (var x))
(val-it my-fn)
有没有办法让它在另一个函数的范围内工作?
【问题讨论】:
标签: clojure functional-programming
我正在尝试读取 Clojure 中函数集合的元数据,但 var 或 reader 特殊形式不起作用,除非它们直接处理符号。
; this works
(var my-fn)
; this doesn't
(defn val-it [x] (var x))
(val-it my-fn)
有没有办法让它在另一个函数的范围内工作?
【问题讨论】:
标签: clojure functional-programming
resolve 返回当前命名空间上下文中与给定符号对应的 Var 或类对象。 ns-resolve 允许您指定在哪个命名空间中解析符号。
(resolve 'my-fn)
;= #'some.ns/my-fn
如果符号无法解析为 Var,则返回 nil。
【讨论】:
(map resolve ['one 'two 'three])
(map resolve '[+ - /]) => (#'clojure.core/+ #'clojure.core/- #'clojure.core//)。您尝试过哪些没有按预期工作的方法?
(var my-fn)确实直接处理符号,因为它是一种特殊形式(读者收到未评估的形式)。
您要读取的元数据存储在var 对象中,而不是函数对象中。
因此,您的目标,即从函数对象列表中读取元数据,只能通过遍历所有现有变量并通过相等性比较它们的值来实现。如果函数对象是唯一的开始方式,我只会推荐它。
(defn meta-of
"Returns a hashmap mapping the function objects in fn-objs to
a set of metadata of vars containing it."
[fn-objs]
(let [fn-objs (set fn-objs)]
(reduce (fn [acc ns]
(reduce (fn [acc var]
(let [val (var-get var)]
(cond-> acc
(contains? fn-objs val)
(update-in [val] (fnil conj #{}) (meta var)))))
acc
(vals (ns-interns ns)))) {} (all-ns))))
(def foo inc) ;; Now there are two vars that have the inc function as their value
(meta-of [inc])
{#<core$inc clojure.core$inc@66d7e31d> ;; <- function object
#{{:ns #<Namespace clojure.core>, ;; <- metadata in clojure.core namespace
:name inc,
:file "clojure/core.clj",
:column 1,
:line 881,
:arglists ([x]),
:added "1.2",
:inline #<core$inc__inliner clojure.core$inc__inliner@24f87069>,
:doc
"Returns a number one greater than num. Does not auto-promote\n longs, will throw on overflow. See also: inc'"}
{:ns #<Namespace user>, ;; <- metadata in user namespace
:name foo,
:file "/tmp/form-init1078564431656334911.clj",
:column 1,
:line 1}}}
【讨论】: