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

时间:2011-06-22 17:21:56

标签: emacs clojure read-eval-print-loop slime

我正在尝试使用Clojure doc函数获取文档,但无法从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函数并将其识别为函数而不是变量?


ADDENDUM,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)?

感谢所有贡献者。

2 个答案:

答案 0 :(得分:12)

一些纠正。首先,doc是一个宏而不是一个函数。函数和宏也可以存储在var中。其次,在clojure 1.3中,可能是您使用的版本,doc存储在var clojure.repl / doc中,而不是clojure.core / doc(因为它在1.2中)。在命名空间用户中,doc是“used”,也就是说有一个隐含的“(使用[clojure.repl:only [doc])”。当你转到一个新的命名空间,或者甚至用ns创建一个命名空间时,不会自动添加clojure.repl / doc,这与'user。

不同。

更明确地提出问题:

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

clojure中的函数,宏和值要么存储在变量中,要么绑定到符号,例如let或function。 clojure.core / doc是包含执行doc操作的宏的var。

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

与所有lisps一样,无论是函数还是宏,都必须将函数/宏放在列表的第一个位置。

(<fn/macro> *args)

因此,要调用宏文档,您可以这样做:

(doc doc)

答案 1 :(得分:1)

doc for doc显示了一个宏,所以用macroexpand扩展它就是这样 期望包含函数的var的名称。所以对你的问题的简短回答是“命名空间中的函数包含在变量中”。

在像这样的情况下,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
相关问题