简体   繁体   English

如何将Clojure的doc函数应用于一系列函数

[英]How can I apply clojure's doc function to a sequence of functions

I was trying to do something I thought would be simple but has turned out to be not so and I think the solution might give me a deeper understanding of clojure so I figured I'd ask here. 我试图做一些我认为简单的事情,但事实并非如此,我认为该解决方案可能使我对clojure有更深入的了解,所以我想在这里问一下。

I want to be able to run the following from a clojure REPL: 我希望能够从clojure REPL运行以下命令:

(map #(doc %) v)

where v is a vector of...something, I'm not sure what. 其中v是...某物的向量,我不确定是什么。 The goal was to print out the doc strings for some sequence of functions, but I'm not sure how to express that vector. 目的是打印出某些功能序列的文档字符串,但是我不确定如何表达该向量。 I've tried a couple of things: (I'll pick a few functions out at random) 我尝试了几件事:(我会随机选择一些功能)

[+ - first set]
['+ '- 'first 'set]
[`+ `- `first `set]
[(var +) (var -) (var first) (var set)]
[`~+ `~- `~first `~set]

None work. 没有工作。 I also tried to apply the doc function but that doesn't work since doc is a macro and as such cannot be an argument to apply . 我也尝试apply doc函数,但是由于doc是一个宏,因此不能作为apply的参数,因此无法正常工作。 What am I missing? 我想念什么?

(doseq [f ['+ '- 'first 'set]] (eval (list 'doc f)))

In Clojure 1.2 you can use the function print-doc : 在Clojure 1.2中,您可以使用函数print-doc

(print-doc #'fisrt)

like this 像这样

(map print-doc [#'fisrt #'+])

#'fisrt is the same as (var first) . #'fisrt(var first)相同。

Note that this will not work for special forms: (doc def) works, but (print-doc # def)` gives: 请注意,这不适用于特殊形式: (doc def)有效,但是(print-doc # def)`给出:

java.lang.Exception: Unable to resolve var: def in this context (NO_SOURCE_FILE:7)

This is because special forms aren't defined in vars. 这是因为在vars中没有定义特殊形式。 You can see how doc works for them by using macroexpand-1 : 您可以使用macroexpand-1查看doc如何为它们工作:

user=> (macroexpand-1 '(doc def))
(clojure.core/print-special-doc (quote def) "Special Form" (clojure.core/special-form-anchor (quote def)))

In Clojure 1.3 print-doc is moved in the clojure.repl namespace and is private, so you cannot execute it directly. 在Clojure 1.3中, print-docclojure.repl命名空间中移动并且是私有的,因此您不能直接执行它。 You can enter the ns: 您可以输入ns:

user=> (in-ns 'clojure.repl)
clojure.repl=> (print-doc (meta #'first))
clojure.repl=> (map #(print-doc (meta %)) [#'first #'+])

As you can see, Clojure 1.3 requires getting the metadata explicitly. 如您所见,Clojure 1.3需要显式获取元数据。

If you need to execute this from a different namespace you'll have to export the function. 如果需要从其他名称空间执行此操作,则必须导出函数。 One way to do so is to define a new function: 一种方法是定义一个新函数:

clojure.repl=> (defn my-print-doc [m] (print-doc m))
user=> (clojure.repl/my-print-doc (meta #'first))
(defn my-doc [v] (-> v meta :doc))

This function takes the meta data of a var and then gets the doc string out of the meta data. 此函数获取var的元数据,然后从元数据中获取doc字符串。 You can map it over a sequence of vars: 您可以将其映射到一系列变量上:

(map my-doc [(var +) (var -) (var first) (var set)]) ;=> LazySeq of doc-strings

or shorter: 或更短:

(map my-doc [#'+ #'- #'first #'set]) ;=> LazySeq of doc-strings

This doesn't work for special forms, since they are not referenced by vars. 这不适用于特殊形式,因为它们没有被vars引用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM