Macros are one of the most talked about features of Lisp. They are a powerful way to extend the language without modifying the compiler.
A common failure in distributed systems is a server with a rate limit or with no limit but begins failing due to load. A standard solution is to retry after waiting a small time, increasing that time after each failure. We create a macro to handle this waiting and retrying.
Distributed systems fail in indistinguishable ways. Often, retrying is a good solution to intermittent errors. We create a retry macro to handle the retries in a generic way.
Macros should be avoided to the extent possible. There are three circumstances where they are required.
Lisp with macros can be seen as two languages, each with different semantics. The base language can be interpreted directly, whereas the result of interpreting the macro language is to produce a new program in the base language.