21.6 More hygiene
We shall make one more note about hygiene: In a textual substitution macro, there is a chance that the global variables that the macro uses (in this case, the helper function define-aircraft) could be confused with a surrounding local variable of the same name where the macro is called. This confusion does not happen in a Dylan macro. The global variables used in a Dylan macro always denote what they denoted at the time that the macro was defined, rather than at the time that the macro is called. It is as though the variables were automatically renamed so that conflicts will be avoided.
You will also notice this feature if you export a macro from a module. Only the macro needs to be exported. Its global references still refer to the proper (module-private) values that they had at the time the macro was defined, just as occurs when a function exported from a module calls module-private subroutines.
Occasionally, you will want to circumvent macro hygiene. You may want to define a macro that creates a variable that is visible at the macro call. Here is a simple statement macro that repeats its body until you ask it to stop!:
define macro repeat
{ repeat ?:body end }
=> { block (?=stop!)
local method again() ?body; again() end;
again();
end }
end macro repeat;
The term ?=stop! says that the local variable stop!, which is the block exit variable, will be visible when the macro is called exactly as stop!; there will be no hygienic renaming. Here is an example that uses the macro to count to 100:
begin
let i = 0;
repeat
if (i == 100) stop!() end;
i := i + 1;
end;
end;
Note that the body constraint invokes the Dylan parser to match the code properly between the repeat and the corresponding end. It is not confused by the end of the if statement, as a text-based macro might be. The expanded view of the preceding code might look like this:
begin
let i = 0;
block (stop!)
local method again()
if (i == 100) stop!() end;
i := i + 1;
again()
end;
again();
end;
end;
Note that we have shown the local variable stop! introduced by the macro block in code font rather than in underline italic, because it is visible to the body and is exactly the stop! called in the if to stop the repetition. The local variable again, on the other hand, is not visible to the body code. We could use again instead of i as our repetition count without a problem.
Note that we would have to document how repeat works for other users, or they might be surprised if they tried to use stop! instead of i in the example.




