Clojure 无法从命名空间获取随机(doc)

Clojure 无法从命名空间获取随机(doc),clojure,Clojure,我想显示一些名称空间的随机(doc)页面 我可以通过以下方式获得随机函数名: user=> (rand-nth (keys (ns-publics 'clojure.core))) unchecked-char 当我尝试将其传递给(doc)时,我得到以下结果: user=> (doc (rand-nth (keys (ns-publics 'clojure.core)))) ClassCastException clojure.lang.PersistentList cannot

我想显示一些名称空间的随机(doc)页面

我可以通过以下方式获得随机函数名:

user=> (rand-nth (keys (ns-publics 'clojure.core)))
unchecked-char
当我尝试将其传递给(doc)时,我得到以下结果:

user=> (doc (rand-nth (keys (ns-publics 'clojure.core))))
ClassCastException clojure.lang.PersistentList cannot be cast to clojure.lang.Symbol clojure.core/ns-resolve (core.clj:3883)

我是Clojure的新手,我不知道该怎么处理这个。。。我试图将其转换为regexp并使用(find doc),但可能有更好的方法来实现这一点…

解释

这里的问题是
doc
是一个宏,而不是一个函数。您可以使用repl中的宏来验证这一点

(source doc)

; (defmacro doc
;   "Prints documentation for a var or special form given its name"
;   {:added "1.0"}
;   [name]
;   (if-let [special-name ('{& fn catch try finally try} name)]
;     (#'print-doc (#'special-doc special-name))
;     (cond
;       (special-doc-map name) `(#'print-doc (#'special-doc '~name))
;       (resolve name) `(#'print-doc (meta (var ~name)))
;       (find-ns name) `(#'print-doc (namespace-doc (find-ns '~name))))))
如果您是Clojure(和lisps)新手,您可能还没有遇到宏。作为一个极其简单的解释,函数在计算代码上运行,宏在未计算代码上运行——也就是源代码本身

这意味着当你输入

(doc (rand-nth (keys (ns-publics 'clojure.core))))
doc
尝试在实际代码行上操作-
(rand nth(key(ns publics'clojure.core))
-而不是计算结果(返回的符号)。代码只不过是Clojure中的一个列表,这就是为什么错误告诉您不能将列表转换为符号

解决方案

因此,您真正想要做的是计算代码,然后调用结果的
doc
。我们可以通过编写另一个宏来实现这一点,该宏首先计算您提供给它的代码,然后将其传递给
doc

(defmacro eval-doc
 [form]
  (let [resulting-symbol (eval form)]
   `(doc ~resulting-symbol)))
您可以传递
eval doc
任意表单,它将在传递到
doc
之前对其进行评估。现在我们可以走了

(eval-doc (rand-nth (keys (ns-publics 'clojure.core))))
编辑:

尽管上述方法在repl中工作得很好,但如果使用提前编译,您会发现每次都会产生相同的结果。这是因为
let
语句中的
结果符号是在编译阶段生成的。提前编译一次意味着将该值烘焙到.jar中。我们真正想要做的是将
doc
的计算推送到运行时。因此,让我们将
eval doc
重写为一个函数

(defn eval-doc
  [sym]
  (eval `(doc ~sym)))

就这么简单。

Thank you@Beyamor,它在REPL中起作用,但是当我在一个新的Leiningen项目中尝试调用它时”(rand nth(key(ns publics的clojure.core))“总是会产生相同的结果(ns cotd.core(:gen class)(:use[clojure.REPL:only(doc)])(defmacro eval doc[form](let[resulting symbol(eval form)])`(doc~结果符号)))(defn-随机函数名[](rand nth(key(ns publics'clojure.core)))(defn-main“Display randoc page”[&args](eval doc(随机函数名)))啊。对不起,我没有想到。我已经编辑了上面的答案。如果还有其他问题,请告诉我,并感谢您的耐心。仅供参考:您现在可以使用此: