Scheme programs can define and use new derived expression types, called macros. Program-defined expression types have the syntax
(<keyword> <datum> ...)
where is an identifier that uniquely determines the expression type. This identifier is called the syntactic keyword, or simply keyword, of the macro. The number of the s, and their syntax, depends on the expression type.
Each instance of a macro is called a use of the macro. The set of rules that specifies how a use of a macro is transcribed into a more primitive expression is called the transformer of the macro.
The macro definition facility consists of two parts:
- A set of expressions used to establish that certain identifiers are macro keywords, associate them with macro transformers, and control the scope within which a macro is defined, and
- a pattern language for specifying macro transformers.
The syntactic keyword of a macro may shadow variable bindings, and local variable bindings may shadow keyword bindings. All macros defined using the pattern language are "hygienic" and "referentially transparent" and thus preserve Scheme's lexical scoping:
- If a macro transformer inserts a binding for an identifier (variable or keyword), the identifier will in effect be renamed throughout its scope to avoid conflicts with other identifiers. Note that a define at top level may or may not introduce a binding; see section5.2.
- If a macro transformer inserts a free reference to an identifier, the reference refers to the binding that was visible where the transformer was specified, regardless of any local bindings that may surround the use of the macro.
There's no unfamiliar words in this part of article.
A scheme macro is consist of a number of transforming rules. Each rules contain a pattern and a template. In the processing of a macro, firstly it will match the calling syntax given with the patterns, and then expand according to the template defined.
A macro can have a list of syntactical keywords, which in a pattern should be matched exactly with the input, i.e. the calling syntax.
Macros in scheme are hygienic. That means, it will not cause a name pollution even if the usage and the argument-expressions passed are conflict. An implementation should cope with this situation. The article mentioned a method to rename all duplicated symbols that cause a conflict. The binding of the expansion environment is the environment where the macro's defined. (NOT where the macro's expanded.) That means the following code:
(define baz 100)
(define-syntax foo
(syntax-rules ()
((foo baz)
(display (list bar baz)))))
(let ((bar 10))
(foo bar))
will produce (100 10)
.
I've been implementing a scheme interpreter in the whole vacation, in which the most challenging part of that is the implementation of the macros.
Macro is a crucial component of lisp dialects, macro expansions gives lisp extraordinary power to control everything. Especially in scheme, the macro is even more convenient to users. You'll be able to use syntax like:
(define-syntax let
(syntax-rules ()
((let ((var init) ...)
body ...)
((lambda (var ...) body ...)
init ...))))
to define a macro. This way's more intuitive than the common lisp's one, in which the only thing you need to do is declare what form of macro you want to accept, and what should it be after expansion. All the transformation work are handled by the interpreter.
This chapter helps a lot. Since I was working on a formal implementation and this documentation is from official, with detailed and precise specification and explanation of why it's designed as that.