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行

;在引导阶段我们还没有解构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-form true》)所述的那样,是一个特殊形式,那么为什么((special-form? loop))返回false呢?
可能是第二个def造成的。
因为实际上,《_LOOP_》不是特殊形式。按照定义,在任何《clojure.core》中定义的东西都不是特殊形式。您可以看到特殊形式的列表如下:

```
用户=>(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代码中它们进行反解结构,然后调用不需要关心反解结构的特殊形式。
@dpsutton -- 你应该把这个评论写成答案,然后我们就可以给它投票并关闭这个问题。
。
@dpsutton 好的,因此名为 "特殊形式" 的宏是围绕实际特殊形式的薄包装。这很有道理。
如 @Sean 建议,如果您将评论移至答案中,我会很高兴接受它。
...