In Clojure, why is do
a special form, instead of a function implemented like this?
(defn do [& exprs]
(last exprs))
fn
(well, fn*
) actually reuses the logic behind do
, as do other forms with bodies – let*
, letfn*
, try
. Since there are several of these, it makes sense to have them reuse the basic "evaluate expressions in sequence" logic; and since this in itself is useful to user code outside the context of the more complex special form, it makes sense to expose it as do
.
Were fn*
the basic special form instead, sequentially evaluating expressions would involve making a function call – the overhead of that would not be acceptable for this sort of low-level facility.
(On the other hand, replacing the other special forms with macros wrapping their bodies in implicit do
s wouldn't introduce any overhead. In the context of the Clojure compiler as it stands, however, it wouldn't be a huge win either – on this point at least it's fairly DRY already.)
do
Additionally, top-level do
s are treated specially by the compiler in that
(do
(foo)
(bar))
is equivalent at top level (and only at top level) to
(foo)
(bar)
– that is, to the individual expressions written out separately. This allows macros to output (code equivalent to) multiple top-level expressions.
It wouldn't be impossible to interpret top-level calls to some special function in this way, but using a special form for this purpose is significantly cleaner.