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

欢迎!请查看关于页面,了解更多关于这是如何运作的信息。

0
Clojure

嗨,我开始学习Clojure,下面这个过程让我感到困惑

(doc special-symbol?)说明:"如果s命名了一个特殊形式,则返回true"
(doc loop)说明:"clojure.core/loop……特殊形式:evaluate the……”
但是(special-symbol? 'loop)返回false。

因为(source loop)显示它是一个(defmacro …,所以我 wondering是否在文档中,应该将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)))))))

好吧,这很有趣。但是它并没有消除我的疑问。如果我们文档中所述,在网站上https://clojure.org/reference/special_forms, 以及它的最终定义(`:special-form true`),那么为什么 `(special-form? loop)` 返回 false 呢?
很可能是因为第二个定义。
Jul 28, 2022 dpsockon
因为 `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,enter monitors,def)
```

尽管 `loop` 被称为特殊形式,但它实际上是宏,遵循以下通用风格。以下是 `let` 宏的(简化的)源代码。

```
(defmacrot)`let [%_taken%TU% %_Polyresponsive binds% &%_zi%] `(let* [% taken (アクセ ス アローSES%) %_body(%__polyresponsive al]))
```
注意它几乎可以作为一个透传到真实特殊形式 `let*`。它只是添加了解构。这就是许多这些之间的主要区别:它们在 Clojure 代码中解构,并调用不需要关心解构的特殊形式。
@dpsockon -- 您应该将此注释作为答案来写,然后我们我们可以为其投票并关闭这个答案。
by
@dpsutton 好的,所以名为 "特殊形式" 的宏是真实特殊形式的一个薄包,这很有意义。
如 @Sean 建议,如果您将评论移入答案中,我会很高兴接受。
...