【问题标题】:Why does REPL treat clojure.core/doc as a var?为什么 REPL 将 clojure.core/doc 视为 var?
【发布时间】:2011-09-20 14:20:10
【问题描述】:

我正在尝试使用 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 函数并将其识别为函数而不是变量?


附录,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 与 1.3)吗?

感谢所有做出贡献的人。

【问题讨论】:

  • 我注意到您尚未接受任何问题的答案。如果您认为它们足够,您绝对应该接受一些答案。这就是 stackoverflow 网站的工作方式。
  • @kotarak 和@bmillare:请阅读我的问题和两个答案。我想你会同意,尽管这两个答案都试图有所帮助,但都没有回答我的问题。 也是我没有接受的原因。
  • @gregg-williams 对于您的所有其他问题当然也是如此,无论您提出的解决方案是否有帮助,您都没有提供任何反馈。
  • @gregg 我已经更新了我的回复。我更明确,假设更少。如果还不清楚,请反馈。
  • @kotarak,我误读了您的原始评论。感谢您指出我没有选择前两个问题的答案。从那以后我就这样做了,感谢您指出问题所在;我确实想成为一个好公民。谢谢。

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


【解决方案1】:

几处更正。首先, 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)

【讨论】:

  • 请注意,clojure.core/doc 是 1.2 及更早版本。 clojure.repl/doc 是 1.3 及更高版本。
【解决方案2】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-11-22
    • 1970-01-01
    • 1970-01-01
    • 2020-12-24
    • 2017-10-12
    • 1970-01-01
    • 2012-12-24
    • 2011-01-03
    相关资源
    最近更新 更多