Chapter 24. Metaprogramming: Macros and Reflection

Metaprogramming is programming that manipulates programs as data. In some languages, the difference between programming and metaprogramming isn’t all that significant. Lisp dialects, for example, use the same S-expression representation for code and data, a property called homoiconicity. Dynamically typed languages like Python and Ruby make it easy to manipulate the program with other code, sometimes derisively called monkey patching. In statically typed languages like Java and Scala, metaprogramming is more constrained and less common. It’s still useful for solving many advanced design problems, but more formality is required to separate compile-time versus runtime manipulation.

Metaprogramming comes in many forms. The word reflection refers to introspection of code at runtime, such as asking a value or type for metadata about itself. The metadata typically includes details about the type, methods and fields, etc.

Scala macros work like constrained compiler plug-ins because they manipulate the abstract syntax tree (AST) produced from the parsed source code. Macros are invoked to manipulate the AST before the final compilation phases leading to byte-code generation.

While Scala 2 had a metaprogramming system, called Scalameta, it was always considered experimental, even though it was widely used by library writers for advanced scenarios. Scala 3 introduces a new macro system, which is not considered experimental. Replacing Scala ...

Get Programming Scala, 3rd Edition now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.