4 ms·
Emacs is a very important ecosystem that effectively uses macros. The danger of macro overcomplication is real, and emacs' conventions are the primary way they
by shawn 8y ago
Emacs is a very important ecosystem that effectively uses macros. The danger of macro overcomplication is real, and emacs' conventions are the primary way they avoid introducing problems.
For example, macros and functions are nearly the same thing: one runs at compile time, the other at runtime. But they both have documentation, and you can jump to a macro's definition the same way you would for a function. You can also compose them together and generate new ones on the fly, etc.
Basically, a lot of the problems with macros in other languages is that macros are considered this special type of not-really-a-function. It's either templating sugarcoat, or restricted turing-noncomplete layer. But if you treat macros as literally functions that just happen to run at compile time, the problems are reduced. And if you treat them with discipline and document what they do, and show examples, and add test cases, then you never have to worry -- just like normal software.
One helpful rule of thumb: If you copy some functionality more than twice, it's probably time to make it a function. If you define a set of functions repeatedly -- like test cases -- or find yourself writing the same pattern over and over, or if you can generate most of your structure automatically based on e.g. "I know this is a React component", it might be time to write a macro.
If this concept sounds intriguing to anyone, I highly encourage you to check out Lumen: https://github.com/sctb/lumen https://github.com/sctb/lumen
It's a Lisp that's literally javascript:
Compiled code: https://github.com/sctb/lumen/blob/master/bin/reader.js https://github.com/sctb/lumen/blob/master/bin/reader.js
Original code: https://github.com/sctb/lumen/blob/master/reader.l https://github.com/sctb/lumen/blob/master/reader.l
So if you understand Javascript, then there's not much to learn. And you can use it in your own projects right away.
Most of Lumen's brevity is thanks to macros.
(One hack for quickly understanding Lumen: read the tests. Every language feature is meticulously demo'd: https://github.com/sctb/lumen/blob/master/test.l https://github.com/sctb/lumen/blob/master/test.l)
- lolive 8y agoAs a OO programmer, I would still argue that: if I define a set of functions repeatedly, I will try to find an elegant object design to abstract that. One good point, then, is that I can debug that object design at any line of code. Whereas (I feel that) macros are undebuggable by design.
- shawn 8y agoSuppose you were forced to use a language with no objects, and no closures. Since you're an effective dev, you'd find ways to cope. But we invented object systems to do better work. Closures were another step up the ladder of abstraction, and now it's hard to imagine not being able to use them. Macros are no different. It seems worth being skeptical of the idea that it's better for a programmer to have less power. And Emacs Lisp shows macros can work at scale without causing friction. To your point on debugging, it all depends on the language. Elisp has an excellent debugging facility: https://www.gnu.org/software/emacs/manual/html_node/elisp/Edebug-and-Macros.html#Edebug-and-Macros https://www.gnu.org/software/emacs/manual/html_node/elisp/Ed... The key is to internalize that macros are no different from functions. If you know how to call a function, you know how to use macros. The only difference is that they return code rather than values.
- lucozade 8y agoThis was kind of my original point though. If you do treat them as compile time functions i.e. for a bit of light code gen then they can be super useful. But that's often not the case. In fact, OO is a nice example. It's probably less true now that OO seems to be a bit out of fashion, but the number of crappy, poorly documented OO systems I've seen in Lisps over the years is staggering. It's not really a criticism of macros so much as an observation. It's also possible that the type of developer who is attracted to adding a bijou OO system into their application is the type of developer that is attracted to Lisps. It may well be the case that adding a macro system to JS wouldn't have the same attraction so wouldn't have the same downside.
- deleted 8y ago[deleted]
- xfer 8y ago> If you know how to call a function, you know how to use macros. Wrong, there are many macros that are impossible to grok without reading the docs carefully, there are also scoping rules. They are nowhere near at the usability of functions, macros should be written judiciously. Most uses of macros can be eschewed by higher-order functions, unless you are making a language.