7 ms·
The power of macros goes beyond just core language features. For example, Racket has a prolog implementation, an OOP implementation, contracts, and much more, a
by smabie 6y ago
The power of macros goes beyond just core language features. For example, Racket has a prolog implementation, an OOP implementation, contracts, and much more, all developed with macros. You can generate HTML, do templating, or write documentation, all with macros. There's a certain magical feeling as a library designer when you can decide upon whatever syntax you want, with absolutely no constraints. Leads to the development of some very cool and clean stuff.
For example, I used Racket macros at my old job as a bio informatics researcher at a hospital to design a DSL to specify bio informatics processing pipelines. You could either write it yourself, or you could use a GUI to manipulate a visual graph of operations and write out the pipeline using the DSL to a file.
These sort of DSL use cases are a lot more common than people think, mostly because they don't think of an API as a new language, merely as some code written in an existing one. When you realize that macros can be used to eliminate all repetition and all patterns, you start to think in a different way.
Designing proper interfaces with macros can be challenging though: you want to provide a nice syntax that is both composable with other macros, and clean.
Also macros allow the core language to be paired down and very simple. Stuff like Scheme, in which all desired features (OOP, actors, async, generators, etc) can be implemented by external packages.
But like I said, I don't use Lisp much anymore. Functional programming with higher kindred types goes a long way in matching the power of macros, albeit in a more structured way. Of course, type systems will always fall short of the unlimited power of macros, but for a lot of problems it's more than sufficient.
Think of Lisp as the prototypical programming language, the essence of transforming symbols into other symbols. Lisp forms the base, on top of which all other features can be implemented.