Racket has a highly expressive macro system that allows stacking arbitrarily many layers of compile-time macro evaluation phases that each may run arbitrary Racket code along the way to producing the fully expanded program that will be executed at run-time. The power of this system is what earns Racket its reputation as a paragon of language-oriented programming, but it, combined with Racket’s dynamically typed nature, begets a propensity for inscrutable error messages when using macros that are not sufficiently defensive in their implementation.
To alleviate this problem, we introduce syntax contracts for use in macro definitions. Syntax contracts provide a mechanism for checking the properties of syntax as it is consumed by a macro, appropriately casting blame upon the injurious party when an error arises that is significantly more meaningful to the typical end-user. Along the way, we gain an ergonomic handle for managing local expansion that lets us more easily write macros that accept other macro forms as “arguments”, leading to the development of safe, generically extensible macros.

