Hygiene

Macro expansions are hygienic, meaning there can be no name conflict between a local binding in scope that calls the macro and a local binding in the macro expansion.

Let us say we have two macros A and B. The expansion of A calls B. The following diagram shows the lexical scopes of bindings used in A and B. The table after describes the scopes in more detail.

╒═════════════════════════════════════╕
│ [1] Module or lexical scope of a    │
│     call to macro A                 │
│                                     │
│  ┌───────────────────────────────┐  │
│  │ [2] Expansion of A            │  │
│  │                               │  │
│  │  ┌─────────────────────────┐  │  │
│  │  │ [3] Expansion of B      │  │  │
│  │  │                         │  │  │
│  │  └─────────────────────────┘  │  │
│  │                               │  │
│  └───────────────────────────────┘  │
│                                     │
╘═════════════════════════════════════╛

╒═════════════════════════════════════╕
│ [4] Module containing definition of │
│     macro A                         │
│                                     │
╘═════════════════════════════════════╛

╒═════════════════════════════════════╕
│ [5] Module containing definition of │
│     macro B                         │
│                                     │
╘═════════════════════════════════════╛

In this table, each lexical scope is identified by its number as “Box 1” through “Box 5”. The table describe which bindings defined in each column’s lexical scope are visible in the lexical scope of each row. For example, the table shows that the only bindings from Box 1 visible in Box 2 are those that are captured by one of Macro A’s pattern variables and included in the expansion.

Definition Visibility Definition Location
Box 1 Box 2 Box 3 Box 4 Box 5
Box 1 All Only if defined with unhygienic reference to name from 1, captured by pattern variable of A Only if defined with unhygienic reference to name from 1, captured by pattern variable of A and recaptured by pattern variable of B    
Box 2 Only if captured by pattern variable of A All Only if defined with unhygienic reference to name from 2, captured by pattern variable of B All  
Box 3 Only if captured by pattern variable of A and recaptured by pattern variable of B Only if captured by pattern variable of B All   All
Box 4       All  
Box 5         All

Breaking hygiene

A template can prefix a binding with ?=. This makes the binding come from and be visible in the macro’s caller. This can be illustrated by an example from Dylan Programming.

Say Definition 1 is the Macro A defined in Box 4, and it is called in Box 1 like so:

let i = 0;
repeat
  if (i == 100) stop!() end;
  i := i + 1;
end

The ?=stop! substitution in line 3 of the macro becomes a reference to a binding visible in Boxes 1 and 2. In Box 1, the binding is visible as stop!. In Box 2 (the expansion itself), the binding is visible as ?=stop! and can be used like any binding (e.g., format-out("%=", ?=stop!)).

Note that that a macro expansion cannot create a new name visible outside of the macro call itself. In other words, Box 2 cannot create a binding for use elsewhere in Box 1 unless Box 1 supplies the name to be defined.

For example, given the macro in Definition 2, one might expect the macro call in Call 2 would print “Hello” twice, but the code does not compile. Because every macro expansion is implicitly surrounded by begin…end as described in Background and Overview, the example expands into Expansion 2. After the macro call, foo is no longer in scope.


Definition 1:

1
2
3
4
5
6
7
define macro repeat
  { repeat ?:body end }
    => { block (?=stop!)
           local method again() ?body; again(); end;
           again();
         end }
end macro

Definition 2:

1
2
3
4
define macro do-then-foo
  { do-then-foo(?:expression) ?:body end }
    => { let ?=foo = ?expression; ?body }
end macro

Call 2:

do-then-foo("Hello\n") format-out(foo) end;
format-out(foo)

Expansion 2:

begin
  let foo = "Hello\n";
  format-out(foo)
end;
format-out(foo)