0

我注意到 Clojure 的 ns 函数有一些奇怪的行为。我认为它并不太关心它的论点的顺序,但显然它可能非常挑剔。

在一个文件中,我有

(ns ^{:doc "Foobar"
      :author "me"}
  foo.bar)

但如果我把它写成

(ns foo.bar ^{:doc "Foobar"
              :author "me"})

我收到以下错误

Exception in thread "main" java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.lang.Symbol

在其他文件中,我将 foo.bar 放在 ns 之后,只要元数据不是 ns 的最后一个参数,它就可以正常运行。这有点烦人,因为在其他文件中,我有一些类似 (:require foo.baz) 的东西,显然必须在 foo.bar 之后,否则它会抛出另一个异常。ns的具体规则是什么?我希望我对 ns 的所有调用都是一致的,现在我不知道该怎么做。

4

1 回答 1

3

这不是关于ns,而是关于 Clojure 的词法语法。

^{...}语法使读者将给定的地图附加到阅读以下表格的结果中。所以,在你的例子中,

^{:doc ... :author ...} foo.bar

实际上是作为foo.bar具有给定元数据的单个符号读入的。显然,如果^{...}是结束括号之间的最后一件事,则阅读器将没有任何东西可以附加这条元数据,因此它会抛出异常(在读取时,因此在任何宏展开之前等)。

在 Clojure 中相当典型的情况是,元数据以各种def类似形式的符号名称(除了那些纯粹用于主机互操作的形式,如definterface)被传输到被定义的事物。基本宏 ( ns, defn, defmacro) 还支持属性映射参数和单独的文档字符串参数:

(ns foo.core
  "Quite a magnificent namespace, and very well-documented."
  {:author "Alice Perr"}
  (:require [foo.protocols :refer [PFoo]]))

(defn fooify
  "Return a PFoo wrapper for x."
  {:added "0.0.1"}
  [x]
  (reify PFoo
    ...))
于 2013-05-24T00:28:55.180 回答