Pedro Rolo
Pedro Rolo

Reputation: 29960

What are the practical differences between special forms and macros?

Are there any practical differences between special forms and macros? In what do they differ?

Upvotes: 20

Views: 3265

Answers (5)

Rainer Joswig
Rainer Joswig

Reputation: 139261

Lisp has certain language primitives, which make up Lisp forms:

  • literal data: numbers, strings, structures, ...
  • function calls, like (sin 2.1) or like ((lambda (a b) (+ a b 2)) 3 4)
  • special operators used in special forms. These are the primitive built-in language elements. See Special Operators in Common Lisp. These need to be implemented in the interpreter and compiler. Common Lisp provides no way for the developer to introduce new special operators or to provide your own version of these. A code parsing tool will need to understand these special operators; these tools are usually called 'code walkers' in the Lisp community. During the definition of the Common Lisp standard, it was made sure that the number is very small and that all extensions otherwise are done via new functions and new macros.
  • macros: macros are functions which are transforming source code. The transformation will happen recursively until no macro is left in the source code. Common Lisp has built-in macros and allows the user to write new ones.

So the most important practical difference between special forms and macros is this: special operators are built-in syntax and semantics. They can't be written by the developer. Macros can be written by the developer.

Upvotes: 11

Luis Casillas
Luis Casillas

Reputation: 30227

The terms aren't quite synonymous, but they aren't exclusive either (this answer assumes Scheme):

  • A special form (also known as a syntax in the Scheme Reports) is an expression that's not evaluated according to the default rule for function application. (The default rule, just to be explicit, is to eval all of the subexpressions, and then apply the result of the first one to the list of the results of the others.)
  • The macro system is a language feature that allows definition of new special forms within the language itself. A macro is a special form defined using the macro system.

So you could say that "special form" is a term that pertains to interface or semantics, whereas "macro" is a term that pertains to implementation. "Special form" means "these expressions are evaluated with a special rule," while "macro" means "here's an implementation of a special rule for evaluating some expressions."

Now one important thing is that most Scheme special forms can be defined as macros from a really small core of primitives: lambda, if and macros. A minimal Scheme implementation that provides only these can still implement the rest as macros; recent Scheme Reports have made that distinction by referring to such special forms as "library syntax" that can be defined in terms of macros. In practice, however, practical Scheme systems often implement a richer set of forms as primitives.

Semantically speaking, the only thing that matters about an expression is what rule is used to evaluate it, not how that rule is implemented. So in that sense, it's not important whether a special form is implemented as a macro or a primitive. But on the other hand, the implementation details of a Scheme system often "leak," so you may find yourself caring about it...

Upvotes: 20

Arthur Ulfeldt
Arthur Ulfeldt

Reputation: 91554

the super short answer for the lazy

You can write your own macroes any time you want, though you can't add special forms without recompiling clojure.

Upvotes: 2

John Pick
John Pick

Reputation: 5650

For me the most practical difference has been in the debugger: Macros don't show up in the debugger; instead, the (typically) obscure code from the macro's expansion shows up in the debugger. It is a real pain to debug such code and a good reason to ensure your macros are rock solid before you start relying upon them.

Upvotes: 4

Matthias Benkard
Matthias Benkard

Reputation: 15759

In contrast to special forms, macro forms can be macroexpanded:

CL-USER(1): (macroexpand '(with-slots (x y z)
                              foo
                            (format t "~&X = ~A" x)))

(LET ((#:G925 FOO))
  (DECLARE (IGNORABLE #:G925))
  (DECLARE (SB-PCL::%VARIABLE-REBINDING #:G925 FOO))
  #:G925
  (SYMBOL-MACROLET ((X (SLOT-VALUE #:G925 'X))
                    (Y (SLOT-VALUE #:G925 'Y))
                    (Z (SLOT-VALUE #:G925 'Z)))
    (FORMAT T "~&X = ~A" X)))
T

Upvotes: 4

Related Questions