Lesson 1: Metaprogramming: programs that write programs.
Learn how to create syntax objects to create quoted code, by analogy to quote; talk about the phase distinction; write some simple macros that generate programs; make (over-)simplified analogy to cutting and pasting code.Lesson 2: Macros are embedded metaprograms.
Demonstrate that macros can refer to identifiers that are in scope. Show that there's no danger of such identifiers getting captured when macros are referentially transparent; refine the idea of cutting and pasting code to being more than just textual replacement -- a variable reference identifies a binding and the generated code reproduces that binding, not necessarily the name.Lesson 3: Macros can introduce identifiers.
Demonstrate how macros can introduce brand new identifiers; show that in hygienic macro systems those identifiers can never refer to existing bindings in any program, only to uses of the same identifier within a macro's templates; show how identifiers given as parameters can generate binding occurrences, bound occurrences, and quoted occurrences of the identifier.If I could get through all of that without pattern matching, that'd be cool, but somewhere along the line the code might just get too hairy without it. (Then again, Lisp defmacro hackers live without it, don't they?) Since pattern matching is orthogonal to the above lessons, I would love to put it off until after mastering metaprogramming, the phase separation, and issues of scope.
Some might claim you can write macros in a hygienic macro system without understanding properly lexically scoped macros, since they're just taken care of for you. That's pretty much doomed to failure, because as a macro writer you need to understand the distinction between names and identifiers in order to know when you can and can't bind a particular identifier.