2024 Clojure状态调查!中分享您的想法。

欢迎!有关该内容如何工作的更多信息,请查看关于页面。

0
Clojure

嗨,我刚开始接触Clojure,对以下内容感到困惑

(doc special-symbol?)表示“如果s命名一个特殊形式,则返回true
(doc loop)表示“clojure.core/loop……特殊形式:评估……”
(special-symbol? 'loop)返回false。

因为(source loop)显示它是一个(defmacro …,所以我怀疑在文档中是否应该将loop称为而不是特殊形式

另外,因为(special-form? 'def)返回true,而def没有源,即它没有定义为宏。

1 答案

+1

loop是一个棘手的东西,在源文件中定义了两次,一次在第37行

;在引导过程中我们没有destructuring let,loop或fn,稍后会重新定义

  clojure
(def
 ^{:macro true
   :added "1.0"}
 loop (fn* loop [&form &env & decl] (cons 'loop* decl)))

您获得的文档来自loop的第二次定义
loop的第一次定义钩入了一些编译器魔法

并且在第4599行

(defmacro loop
  "Evaluates the exprs in a lexical context in which the symbols in
  the binding-forms are bound to their respective init-exprs or parts
  therein. Acts as a recur target."
  {:added "1.0", :special-form true, :forms '[(loop [bindings*] exprs*)]}
  [bindings & body]
    (assert-args
      (vector? bindings) "a vector for its binding"
      (even? (count bindings)) "an even number of forms in binding vector")
    (let [db (destructure bindings)]
      (if (= db bindings)
        `(loop* ~bindings ~@body)
        (let [vs (take-nth 2 (drop 1 bindings))
              bs (take-nth 2 bindings)
              gs (map (fn [b] (if (symbol? b) b (gensym))) bs)
              bfs (reduce1 (fn [ret [b v g]]
                            (if (symbol? b)
                              (conj ret g v)
                              (conj ret g v b g)))
                          [] (map vector bs vs gs))]
          `(let ~bfs
             (loop* ~(vec (interleave gs gs))
               (let ~(vec (interleave bs gs))
                 ~@body)))))))

好的,这很有趣。但这并没有消除我的疑问。如果 `loop` 确实像文档中所述的那样是特殊形式,网站 https://clojure.org/reference/special_forms, 以及其最终定义 (`:special-from true`),那么为什么 `(special-form? loop)` 返回 false 呢?
by
可能是由于第二个 def。
by
因为 `loop` 实际上并不是特殊形式。在 clojure.core 中定义的任何内容根据定义都不是特殊形式。您可以看到特殊形式是

```
user=> (keys clojure.lang.Compiler/specials)
(& monitor-exit case* try reify* finally loop* do letfn* if clojure.core/import* new deftype* let* fn* recur set! . var quote catch throw monitor-enter def)
```

`loop` 被成为特殊形式,尽管它是一个宏,这遵循了以下通用风格。以下是 `let` 宏的来源(概述)。

```
(defmacro let [bindings & body] `(let* ~(destructure bindings) ~@body))
```
请注意,它几乎是一个到实际特殊形式 `let*` 的直接转发。它只是添加了解构。这也是很多这些宏的主要区别:它们在 Clojure 代码中解构,并调用一个不需要担心解构的特殊形式。
by
@dpsutton -- 你应该将此评论作为答案写入,然后我们可以点赞它并关闭此问题。
by
@dpsutton 好的,因此名为 "special forms" 的宏实际上是真正特殊形式的薄包装。这很有道理。
如@Sean建议,如果您将您的评论移到答案中,我会很高兴接受。
...