4 ms·
> Macros bring syntactic abstraction, which is a wonderful thing. It helps make your code clearer, by describing your intent without getting bogged in implement
by _bxg1 6y ago
> Macros bring syntactic abstraction, which is a wonderful thing. It helps make your code clearer, by describing your intent without getting bogged in implementation details (indeed abstracting those details away). It helps make your code more concise and more readable, by eliminating both redundancy and irrelevant details. But it comes at a cost to the reader, which is learning a new syntactic concept for each macro. And so it should not be abused.
I really think this just applies to any kind of indirection - classes, functions, even named constants (vs literals).
- aidenn0 6y agoRight; all abstractions are only as good as they don't leak, but the question is "how easy is it to debug when it does leak?" I think you listed classes, functions, and named constants in approximately the order of debugability too. It can be unclear even which macroexpansions are in play from a backtrace, much less which one caused the breakage. (non inlined) functions are right there in the backtrace, and of course, debugging a named constant is as simple as typing its name into the REPL.
- fiddlerwoaroof 6y agoIn emacs, the macrostep expander solves most of the Macro debugging issues: you usually can expand a macro use, and see exactly what code is being generated or “refactor” the macro away by copying the expansion at a certain level of detail and replacing the original form with it.
- aidenn0 6y agoYes, this is a useful tool; I still maintain that debugging macros with this tool is harder than debugging functions with the various other SLIME tools.
- skybrian 6y agoSyntax changes have different consequences for reading comprehension. You can often skip over a function call, making only a reasonable guess at what the function does and relying on invariants for all function calls. A macro can arbitrarily change the lexical environment of anything contained in it with few constraints, so reading other parts of a file without knowing what each macro does is more precarious. And when it comes to navigating large amounts of code, you do need to stop somewhere; you can't do a depth-first read of everything before doing anything.
- lioeters 6y agoIndeed, for what are classes and functions but specific kinds of macro (roughly speaking); or, macros and classes as special kinds of functions.. I'd include overloading operators in that list. It can be convenient, but comes at a cost to newcomers to the codebase. I suppose any kind of shortcut or abbreviation carries this risk, to increase the cognitive load of the reader - things they have to remember and mentally substitute the shortcuts until they become second nature. (Oh, right, what we call "shortcut" and "indirection" are both examples of abstraction, its value and cost.)
- dreamcompiler 6y ago> I really think this just applies to any kind of indirection - classes, functions, even named constants (vs literals). Disagree. Macros are fundamentally different in that they can change the syntax of the language. As such, they can inhibit the code's readability in ways the other defining forms cannot. Looking up something by name in CL is as simple as meta-dot. But you cannot meta-dot syntax. (Well, you could on a Lisp Machine, but not so much on current CL implementations.)
- _bxg1 6y agoIt's a difference of degree, not of kind. Any indirection forces the user to reason about a constructed concept instead of the literal facts of what's happening. By introducing one, you're making the assertion that the abstract concept is easier to reason about (including any effort required to learn it) than the contents being abstracted away.
- TeMPOraL 6y ago> But you cannot meta-dot syntax. You can C-c M-e the macro form to have SLIME expand it for you inline (read-only), and then navigate around it, using e to expand and c to collapse back. Super useful.
- fiddlerwoaroof 6y ago> you cannot meta-dot syntax I don't understand this? Besides the macrostep expander, meta-dot works on the macro name: reader macros _are_ harder to debug, but they're generally discouraged.
- dreamcompiler 6y agoIt requires more cognitive load to interpret new syntactic constructs. See brundolf's comment herein.
- erik_seaberg 6y agoIf you don't define the macro, you will have to replace it with boilerplate everywhere you would have used it, and constantly rereading all that is more ongoing grunt work than learning what the macro does.