请在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 呢?
by
可能是由于第二个定义。
by
因为 `loop` 实际上不是一个特殊形式。 在 clojure.core 中定义的任何内容都根据定义不是特殊形式。您可以看到特殊形式如下

```
user=> (keys clojure.lang.Compiler/specials)
(& 监控退出 case* try reify* finally loop* do letfn* if clojure.core/import* new deftype* let* fn* recur set! . var quote catch throw 监控进入 def)
```

`loop` 虽然不是一个特殊形式,但被称作特殊形式的理由遵循这种通用风格。以下是对 `let` 宏的(简化的)源代码。

```
(defmacro let [bindings & body] `(let* ~(destructure bindings) ~@body))
```
注意,它几乎是直接将到实际特殊形式 `let*` 的传递。它只是增加了分解。这和许多其他的差别在于:它们在 Clojure 代码中分解,并调用不需要处理的特殊形式。
by
@dpsutton -- 你应该把这个评论当作答案写出来,然后我们可以给它投票并关闭这个问题。
by
@dpsutton 好的,所以名为 "special forms" 的宏是真正特殊形式的薄包装。这很有道理。
如 @Sean 建议,如果您把您的评论移动到答案中,我会很高兴接受它。
...