5 ms·
Metaprogramming goes way beyond what the C preprocessor does. Metaprogramming also cannot necessarily be "hard to read and mantain". Take a look at macros in C
by flavio81 9y ago
Metaprogramming goes way beyond what the C preprocessor does.
Metaprogramming also cannot necessarily be "hard to read and mantain". Take a look at macros in Common Lisp. They are almost the same as a normal function. Yet they do metaprogramming.
> Give me boring, explicit code any day of the week.
With macro metaprogramming you can eliminate boilerplate code / unnecessary copy-paste repetition of code, and this does improve maintainability of the code.
At the same time, replacing 10 repetitions of the same big boilerplate code (similar code, written with slight variations each of the 10 times) with 10 very simple (one line each) calls to a macro, improves readability: because you will easily read what is the difference between those 10 calls each.
- joshuamorton 9y agoMacro metaprogramming can (and in practice often does) break ctrl+f search. If I want to find the definition of PREFIX_varname, I'd expect to grep for "PREFIX_varname", but often, the correct solution is to search solely for varname, because PREFIX_varname is defined by a call to MACRO(varname).
- KirinDave 9y agoMaybe don't use such a primitive editor integration? I'm not trying to dunk on your editor, but people have had this problem solved since the early 90s. If your programmer's editor doesn't have some affordances for your language, then it's not a programmer's editor at all, it's a text editor.
- joshuamorton 9y agoI'm curious: what editor can do this? Consider that the codebase I work on is large enough that it cannot fit in a project file or ctags or similar. (Which is to say that VS, Clion, and others don't work, nor will vim (for this specific feature))
- KirinDave 9y agoFor which language? In the case of systems like Clojure, if you're introducing new toplevel bindings you're not going to get completion without direct interactive evaluation (naturally). But everything short of that should be well-formed. In many cases with common macros I'd add decls for Cursive Clojure + Idea to let me autocomplete introduced bindings. For example, I helped my editor understand unique structure, e.g., (defauthedendpoint get-frobnaz [request user] ...re<tab>quest)
- joshuamorton 9y agoC/C++. In the general case, I don't believe its possible to resolve macros without linking.
- KirinDave 9y agoActually, I'm not sure. If we're referring to the C pre-processor here, can't we always just run it through before symbolizing? I guess that without the right environment ifdef stuff falls out, but I dunno what to tell you there other than making builds contingent on the environment is a sketchy practice.
- joshuamorton 9y agoSo, say I have this: #include a.h #include b.h #include c.h MACRO(varname) welp.
- KirinDave 9y agoSince the include chain has to terminate, can't we just run the pre-processor over every file before we index it? Seems, um, like a pretty reasonable idea to me if you care about C-style macros (I sure don't.)
- majewsky 9y agoIt may be sketchy, but you may not have a choice. If you have a Qt application (written in C++) which needs to use a platform-specific API to do some magic stuff with a window, there's a method on the window to get the handle that the platform's GUI library offers. Of course that's going to be dependent on the environment because each environment has an entirely different GUI library (e.g. Cocoa only exists on macOS, not on Windows or Linux or Android).
- yellowapple 9y agoOn the other hand, if my editor has to incorporate a full-blown parser for your program's (meta)language in order for me to find where something's defined, then maybe your program needs refactored more than my editor needs replaced. Or perhaps better documentation on your program's part and/or better education/familiarization on my part is warranted. Most modern editors are able to horizontally scroll and thus handle long lines in source code. That doesn't make a 500-character-long line of code acceptable by any stretch.
- KirinDave 9y ago> On the other hand, if my editor has to incorporate a full-blown parser for your program's (meta)language in order for me to find where something's defined, then maybe your program needs refactored more than my editor needs replaced. Either you want your editor aware of your language's semantics if you don't. I rather do, because it saves a ton of time and basic integrations are usually quite straightforward in 2017. > Or perhaps better documentation on your program's part and/or better education/familiarization on my part is warranted. Barring my opinions on this, I don't get why this would exclude editor semantics. > Most modern editors are able to horizontally scroll and thus handle long lines in source code. That doesn't make a 500-character-long line of code acceptable by any stretch. Okay, but this is a false equivalence. You're telling me not to use metaprogramming tools because they make it hard for a specific editor feature to be used in conjunction with them in the most difficult case for any system (introducing new run-time-dependent lexical bindings into a scoped block and handling that at compile time). But unlike code visibility, in most good solutions exist to work with these systems (within reason).
- flavio81 9y agoYou are speaking about C macros, which have almost nothing in common to Lisp's macros. There is no such problem with Common Lisp macros.
- kazinator 9y agoThere could be such a problem with Lisp macros, if the programmers are complete idiots. C programmers gluing together symbols from pieces so that MACRO(PREFIX) expands to some PREFIX_var or whatever are often not complete idiots; they are desperately doing whatever they can to simplify what they are doing in the best way that is supported by the portable language.
- falcolas 9y agoLisp macros go far beyond what is possible in Python/Ruby, and oddly enough are less of a problem because of that. In Python and Ruby, the inability to change the underlying syntax makes alot of developers go to absurd lengths to create new syntax around the existing syntax. And that's what makes Python/Ruby metaprogramming really painful to understand. That said, my (admittedly few) days spent debugging bad macros were pretty damned bad. Having to inspect the results of the macro expansion and figure out what went wrong is not my idea of a good time. And that doesn't even account for reader macros.
- kazinator 9y agoIf a macro is correctly expanding, but you have to go into the expansion to find out what is going wrong when the macro is misused, that means the macro lacks robustness; it is not checking arguments, or not sufficiently or in the right way for the cases you're running into. Bad arguments make their way into the expansion and then trigger errors which are conveyed in terms of the expansion, not necessarily making sense to the macro user. It takes extra time and effort to make macros that are suitable for broader use (people other than the macro writer).
- falcolas 9y agoAgreed on all points. But ultimately, bugs in software happen, and bugs in macros can be a pain in the butt to debug. The extra steps to go in and expand the macro, and then translate the fix in that expansion into a fix for the macro itself gets complicated, fast.
- kazinator 9y agoThe job of the macro is to convert a form into an expansion. If it's doing the job wrong, I don't see how you can avoid looking at the output. With respect to what is that "extra". It's no different from any other "input -> process -> output" computing situation where the output is wrong, the right output is obvious, and you have work back into the process to make that output come out. You shouldn't be fixing macro output. If the macro is wrong, the first step is to find the simplest macro invocation which reproduces the problem. Use a dummy argument for anything irrelevant, and use an atom for any argument that allows one. For any argument position which accepts a list of items, see if the problem reproduces with an empty list, or a list of just one. If you can see the problem in (mymac (a b) c d), you have it made. Hey look, b is being wrapped in an extra list, and d should be quoted."