vineri, 5 februarie 2010

Syntactic closures

This is an alternate take on macro hygiene, proposed by Alan Bawden and Jonathan Rees in MIT AI Memo 1049.

Their solution allows (and forces) the macro writer to control the scoping of identifiers. "In the same way that closures of lambda-expressions solve scoping problems at run time, we propose to introduce syntactic closures as a way to solve scoping problems at macro expansion time."

"Like the closure returned by a lambda-expression, a syntactic closure consists of an environment of some kind, a list of names, and an expression". They are created by a procedure make-syntactic-closure which takes three arguments and returns "a closure of the expression in the environment, leaving the names free".

"The programmer defines macros by writing procedures called expanders. An expander is applied to a syntactic environment and an expression, and returns a syntactic closure. The expression is the piece of program text that is to be expanded, and the syntactic environment is derived from the context in which the expression occured. The resulting syntactic closure is to be used in place of the original expression."



The pattern is as follows:
  1. The subexpressions of the input expression are closed in the syntactic environment in which they occured (argument to the expander)
  2. An expression is created that is the expansion of the original expression, which will include as subexpressions the syntactic closures created in step 1.
  3. The expansion is then closed in a syntactic environment known to the expander, such as the standard Scheme syntactic environment

"This avoids all capture problems by carefully closing each expression in the syntactic environment appropriate to the names it contains. Thus, the subexpressions of the input are closed in the environment of the input, and any new names introduced by the expander are resolved in an environment known to the expander."

The list of names passed to make-syntactic-closure is used in situations where the programmer wants capture to occur. Those names will be left free in the resulting expression, so they can be captured by the lambda-expression in which they are embedded.

Overall, this is a fairly simple low-level solution. It has the disadvantage that hygiene is not provided automatically, and that it is hard to define a pattern-matching language on top of it due to the fact that the syntactic role of an identifier in the input expression is not generally apparent (until macroexpansion makes it so).

Niciun comentariu:

Trimiteți un comentariu