2 ms·
I ended up writing the equivalent of lisp macros in C++, of all languages. One thing that helped greatly with that is the “defer” statement. It lets you defer
by sillysaurusx 5y ago
I ended up writing the equivalent of lisp macros in C++, of all languages.
One thing that helped greatly with that is the “defer” statement. It lets you defer a section of code to the end of the current scope. Which means you now have compile time access to the entire current scope.
We’re writing a compiler for custom ML hardware using MLIR. MLIR has the concept of a current insertion point when you’re building an AST.
emacs users will know where I’m going with this.
We now have a save_excursion macro which stores the current cursor, then resets it at the end of the scope automatically. So when you’re building a loop or an if statement, you normally have to call (pseudocode):
make loop
set cursor to loop body
make statements inside the loop
set cursor to “after loop body”
Now it’s
make loop
save_excursion();
make statements inside the loop
Notice that the work decreased by 25% (three lines instead of four). In C++ land especially, this is a big win.
The “make loop” part is actually so long that our linter breaks it onto several lines. But after making a macro for it, it looks like:
affine_for(loop, idx, 0, n, 1);
make statements inside the loop
And the statements in the loop can of course reference “idx”, the iteration variable, or “loop” (a first class object representing a for loop).
Boom, now the work is cut by 50%. Two lines of code. Technically it went from three to one, and it’s far more readable.
The usual lisp disciplinary rules apply. You need to be familiar with variable capture, and how to make variable names at compile time. (In C++ I use a UNIQ(x) macro, which gives me a unique name for x. You can capture it into a #define by making a second #define and passing UNIQ(x) into it. So in practice most macros like save_excursion become two #defines, since you have to reference the unique name of the variable to store the cursor.)
I don’t know if it’s common. I assume not. Most lispers are rightly allergic to C++. But most lispers also lose the benefits of working in a team setting — so in practice, porting as much benefit from lisp to other languages is the biggest win of all. And that requires you to learn lisp. (Interested readers should look up the Blub Paradox, then move on to studying On Lisp.)