Reflection 如何应用clojure';s doc函数转换为一系列函数
我试图做一些我认为很简单的事情,但事实证明并非如此,我认为这个解决方案可能会让我对clojure有更深的理解,所以我想在这里问一下 我希望能够从clojure REPL运行以下内容:Reflection 如何应用clojure';s doc函数转换为一系列函数,reflection,clojure,Reflection,Clojure,我试图做一些我认为很简单的事情,但事实证明并非如此,我认为这个解决方案可能会让我对clojure有更深的理解,所以我想在这里问一下 我希望能够从clojure REPL运行以下内容: (map #(doc %) v) 其中,v是……某物的向量,我不确定是什么。目标是打印出一些函数序列的文档字符串,但我不确定如何表示该向量。我已经尝试了两种方法:(我将随机挑选一些函数) 没用。我还尝试了apply应用doc函数,但这不起作用,因为doc是一个宏,因此不能作为apply的参数。我遗漏了什么?在Cl
(map #(doc %) v)
其中,v
是……某物的向量,我不确定是什么。目标是打印出一些函数序列的文档字符串,但我不确定如何表示该向量。我已经尝试了两种方法:(我将随机挑选一些函数)
没用。我还尝试了
apply
应用doc
函数,但这不起作用,因为doc
是一个宏,因此不能作为apply
的参数。我遗漏了什么?在Clojure 1.2中,您可以使用功能打印文档
:
(print-doc #'fisrt)
像这样
(map print-doc [#'fisrt #'+])
#first
与(var-first)
相同
请注意,这不适用于特殊表单:(doc def)
有效,但(print doc#
def)`提供:
这是因为vars中没有定义特殊形式。通过使用macroexpand-1
,您可以看到doc是如何为它们工作的:
user=> (macroexpand-1 '(doc def))
(clojure.core/print-special-doc (quote def) "Special Form" (clojure.core/special-form-anchor (quote def)))
在Clojure 1.3中,print doc
在Clojure.repl
命名空间中移动,并且是私有的,因此您不能直接执行它。您可以输入ns:
user=> (in-ns 'clojure.repl)
clojure.repl=> (print-doc (meta #'first))
clojure.repl=> (map #(print-doc (meta %)) [#'first #'+])
如您所见,Clojure 1.3要求显式获取元数据
如果需要从不同的名称空间执行此操作,则必须导出函数。一种方法是定义一个新函数:
clojure.repl=> (defn my-print-doc [m] (print-doc m))
user=> (clojure.repl/my-print-doc (meta #'first))
此函数获取变量的元数据,然后从元数据中获取文档字符串。
您可以将其映射到一系列变量上:
(map my-doc [(var +) (var -) (var first) (var set)]) ;=> LazySeq of doc-strings
或更短:
(map my-doc [#'+ #'- #'first #'set]) ;=> LazySeq of doc-strings
这不适用于特殊的表单,因为它们没有被VAR引用。不过我喜欢这样,为了适应我的问题,我将它修改为
(map#(eval(list'doc(symbol%))[+-first set])
如果你不去想的话,我觉得更好。(def v'[+-first set])(map#(eval(list'doc v%));归零
(doseq [f ['+ '- 'first 'set]] (eval (list 'doc f)))
(map my-doc [(var +) (var -) (var first) (var set)]) ;=> LazySeq of doc-strings
(map my-doc [#'+ #'- #'first #'set]) ;=> LazySeq of doc-strings
(doseq [f ['+ '- 'first 'set]] (eval (list 'doc f)))