5

我正在尝试使用 Clojuredoc函数获取文档,但无法从 REPL 中识别它(我正在使用 Emacs 和 SLIME)。以下序列描述了正在发生的事情(错误消息紧跟在每一行之后):

gaidica.core> (doc first)
; Evaluation aborted.

Unable to resolve symbol: doc in this context
  [Thrown class java.lang.Exception]

gaidica.core> (clojure.core/doc first)
; Evaluation aborted.

No such var: clojure.core/doc
  [Thrown class java.lang.Exception]

user> (clojure.core/doc first)
; Evaluation aborted.

No such var: clojure.core/doc
  [Thrown class java.lang.Exception]

user> (doc first)
-------------------------
clojure.core/first
([coll])
  Returns the first item in the collection. Calls seq on its
    argument. If coll is nil, returns nil.
nil
user> 

如何引用doc函数并将其识别为函数,而不是变量?


附录,2011 年 6 月 22 日,问题发布后 9 小时

@kotarak 发表了最相关的评论:“注意,clojure.core/doc 是 1.2 及更早版本。clojure.repl/doc 是 1.3 及更高版本。” 果然,以下工作:

user> (clojure.repl/doc first)
-------------------------
clojure.core/first
([coll])
  Returns the first item in the collection. Calls seq on its
    argument. If coll is nil, returns nil.
nil
user>

我能够确认 Clojure 1.3 处于活动状态:

user> *clojure-version*
{:interim true, :major 1, :minor 3, :incremental 0, :qualifier "master"}
user> 

但这也令人困惑——我的 Leiningen project.clj 指定了 Clojure 1.2!

以我自己的经验,我曾经注意到,即使在我更改了相关目录的内容之后,基于 SLIME 的 REPL “挂在”Java 类路径值上。然后的解决方案是退出 Emacs 和lein swank,然后重新输入两者并重试。我尝试了同样的方法并得到了以下结果:

user> *clojure-version*
{:major 1, :minor 2, :incremental 0, :qualifier ""}
user> 

我能得出的唯一结论是我之前的 REPL 一直在使用 Clojure 1.3。我之前从事的项目使用了 Clojure 1.3 快照,所以我猜测 REPL 以某种方式“挂在”Clojure 1.3 上。

问题已解决,经验教训等。对于加分,任何人都可以解释发生的原因(Clojure 1.2 vs. 1.3)吗?

感谢所有做出贡献的人。

4

2 回答 2

12

几个更正。首先, doc 是宏而不是函数。函数和宏也可以存储在 var 中。其次,在 clojure 1.3(可能是您正在使用的版本)中,doc 存储在 var clojure.repl/doc 中,而不是 clojure.core/doc 中(就像在 1.2 中一样)。在命名空间用户中,doc 是“使用的”,也就是隐含的“(使用 [clojure.repl :only [doc])”。当你进入一个新的命名空间,甚至使用 ns 创建一个命名空间时,不会自动添加 clojure.repl/doc,不像使用 'user.

为了更明确地了解这些问题:

为什么 REPL 将 clojure.core/doc 视为 var?

clojure 中的函数、宏和值要么存储在 vars 中,要么绑定到诸如 let 或函数中的符号。clojure.core/doc 是包含执行 doc 功能的宏的 var。

如何引用 doc 函数并将其识别为函数,而不是变量?

就像在所有 lisps 中一样,要进行调用,无论是函数还是宏,都必须将函数/宏放在列表的第一个位置。

(<fn/macro> *args)

所以要自己调用宏文档,你会这样做:

(doc doc)
于 2011-06-22T18:29:54.607 回答
1

doc 的 doc 显示了它的一个宏,因此用 macroexpand 扩展它表明它期望包含一个函数的 var 的名称。因此,对您的问题的简短回答是“命名空间中的函数包含在 vars 中”。

在这种情况下,macroexpand-1 可能是一个不错的起点:

(macroexpand-1 '(doc doc))
(clojure.core/print-doc (var doc))
sso-config.core> (doc doc)
-------------------------
clojure.core/doc
([name])
Macro
  Prints documentation for a var or special form given its name
于 2011-06-22T20:33:21.860 回答