为什么是特殊形式?
Why is do a special form?
在 Clojure 中,为什么 do
是一种特殊形式,而不是像这样实现的函数?
(defn do [& exprs]
(last exprs))
基本顺序执行语义
fn
(好吧,fn*
)实际上重用了 do
背后的逻辑,就像其他带有正文的形式一样 – let*
、letfn*
、try
。由于其中有几个,让它们重用基本的 "evaluate expressions in sequence" 逻辑是有意义的;由于这本身对更复杂的特殊形式上下文之外的用户代码很有用,因此将其公开为 do
.
是有意义的
如果 fn*
是基本的特殊形式,顺序计算表达式将涉及进行函数调用——这种低级设施的开销是不可接受的。
(另一方面,用隐含的 do
s 包装它们的主体的宏替换其他特殊形式不会引入任何开销。然而,在 Clojure 编译器的上下文中,它也不会是一个巨大的胜利——至少在这一点上它已经相当干燥了。)
顶级do
此外,顶级 do
由编译器特殊处理
(do
(foo)
(bar))
在顶层(且仅在顶层)等同于
(foo)
(bar)
——也就是把各个表达式分开写出来。这允许宏输出(代码等效于)多个顶级表达式。
以这种方式解释对某些特殊函数的顶级调用并非不可能,但为此目的使用特殊形式要清晰得多。
在 Clojure 中,为什么 do
是一种特殊形式,而不是像这样实现的函数?
(defn do [& exprs]
(last exprs))
基本顺序执行语义
fn
(好吧,fn*
)实际上重用了 do
背后的逻辑,就像其他带有正文的形式一样 – let*
、letfn*
、try
。由于其中有几个,让它们重用基本的 "evaluate expressions in sequence" 逻辑是有意义的;由于这本身对更复杂的特殊形式上下文之外的用户代码很有用,因此将其公开为 do
.
如果 fn*
是基本的特殊形式,顺序计算表达式将涉及进行函数调用——这种低级设施的开销是不可接受的。
(另一方面,用隐含的 do
s 包装它们的主体的宏替换其他特殊形式不会引入任何开销。然而,在 Clojure 编译器的上下文中,它也不会是一个巨大的胜利——至少在这一点上它已经相当干燥了。)
顶级do
此外,顶级 do
由编译器特殊处理
(do
(foo)
(bar))
在顶层(且仅在顶层)等同于
(foo)
(bar)
——也就是把各个表达式分开写出来。这允许宏输出(代码等效于)多个顶级表达式。
以这种方式解释对某些特殊函数的顶级调用并非不可能,但为此目的使用特殊形式要清晰得多。