Live data from Hacker News

Macros on Steroids: How pure C can benefit from metaprogramming

hirrolot.github.io

1–10 of 63 posts

Re: Macros on Steroids: How pure C can benefit from metaprogramming

#3
There are good reasons to reach for macro libraries. They're rare, but they're out there. I make heavy use of boost::preprocessor in a C project and it was fundamentally enabling. I have occasionally cursed at it but never regretted it.

It is basically impossible to provide a "kind" development environment using deep macro trickery. The error messages you get from this kind of library are a major handicap. This failing is intrinsic to the landscape and not something you can really fix.

Historically, macro processors in major compilers were inconsistent, limited, and arbitrary, making heavy macro use frustrating, limited, non-portable. I think this is mostly historical now.

IMO people should prefer boost::preprocessor for purposes like this (even in pure C), since it is battle-tested and more polished than "little" metaprogramming libraries will likely ever be. (This is advice to possible users, and not a knock on the author. Props for exploring the space and building something useful.)

Re: Macros on Steroids: How pure C can benefit from metaprogramming

#4
post #3

There are good reasons to reach for macro libraries. They're rare, but they're out there. I make heavy use of boost::preprocessor in a C project and it was fundamentally enabling. I have occasionally cursed at it but never regretted it. It is basically impossible to provide a "kind" development environment using deep macro trickery. The error messages you get from this kind of library are a major handicap. This faili…

> IMO people should prefer boost::preprocessor for purposes like this (even in pure C), since it is battle-tested and more polished than "little" metaprogramming libraries will likely ever be.

In fact, I used to program in boost::preprocessor before, trying to implement ADTs [1]. At the end of the game, I just realised I didn't have enough patience and whatever else to continue using it. I could accidentally see that some macro got blocked and then debugging it for a half of a day to eventually come up with ugly workarounds.

Then I made Metalang99. It has many neat features but really the very motivation for it was to get rid of macro recursion blocking. For example, if you call FOO, then FOO calls BAR, BAR calls JAR, and JAR calls FOO, everything should work as expected. This was a complete nightmare with boost::preprocessor.

So in conclusion, I agree that boost::preprocessor is more polished and can work on ancient compilers too. However, since nowadays the situation with preprocessors is better, I would endeavour to use more modern tools which offer greater convenience and flexibility.

[1]: https://github.com/Hirrolot/poica

Re: Macros on Steroids: How pure C can benefit from metaprogramming

#5
post #3

There are good reasons to reach for macro libraries. They're rare, but they're out there. I make heavy use of boost::preprocessor in a C project and it was fundamentally enabling. I have occasionally cursed at it but never regretted it. It is basically impossible to provide a "kind" development environment using deep macro trickery. The error messages you get from this kind of library are a major handicap. This faili…

If you need these kinds of advanced metaprogramming capabilities then I feel like that's a sign that maybe plain C isn't suitable for your project and you'd better off switching to Zig, Rust, D or C++. These all provide powerful compile-time execution capabilities and the ability to expose C interfaces.

Re: Macros on Steroids: How pure C can benefit from metaprogramming

#6
post #3

There are good reasons to reach for macro libraries. They're rare, but they're out there. I make heavy use of boost::preprocessor in a C project and it was fundamentally enabling. I have occasionally cursed at it but never regretted it. It is basically impossible to provide a "kind" development environment using deep macro trickery. The error messages you get from this kind of library are a major handicap. This faili…

If you need these kinds of advanced metaprogramming capabilities then I feel like that's a sign that maybe plain C isn't suitable for your project and you'd better off switching to Zig, Rust, D or C++. These all provide powerful compile-time execution capabilities and the ability to expose C interfaces.

Only if you can switch to something like Zig, Rust, etc. But a tremendous amount of code bases are already written in plain C. Using preprocessor metaprogramming allows you to invoke macros right in the same files in which you write ordinary C code, without the need for integration with other languages.

Re: Macros on Steroids: How pure C can benefit from metaprogramming

#8
Something about macros that I don't see discussed much is the trade-off between improved clarity of intent vs learning curve for contributors.

I don't have a ton of experience w/ C, but the large projects I've seen appear to have a tendency to avoid heavy macro usage (e.g. using `void *` for hashmap implementations instead of reaching for macros, for example). I see macros appear more frequently among those that prioritize machiavellian cleverness, often under the pretext of squeezing performance: code written by (g|x)ooglers, for example.

I'm curious what more experienced C developers think of jumping into projects with heavy usage of macro-based DSLs, especially the syntax-bending variety being suggested here. Does it get in the way of contributing? Or of reasoning about performance? Etc.

Re: Macros on Steroids: How pure C can benefit from metaprogramming

#9
post #4
post #3

There are good reasons to reach for macro libraries. They're rare, but they're out there. I make heavy use of boost::preprocessor in a C project and it was fundamentally enabling. I have occasionally cursed at it but never regretted it. It is basically impossible to provide a "kind" development environment using deep macro trickery. The error messages you get from this kind of library are a major handicap. This faili…

> IMO people should prefer boost::preprocessor for purposes like this (even in pure C), since it is battle-tested and more polished than "little" metaprogramming libraries will likely ever be. In fact, I used to program in boost::preprocessor before, trying to implement ADTs [1]. At the end of the game, I just realised I didn't have enough patience and whatever else to continue using it. I could accidentally see that…

You're absolutely correct, boost::preprocessor has an obligation towards backwards compatibility that independent efforts do not. This obligation is a double-edged sword: when I pick a library, I want it to be modern; 5 years later, I shouldn't be forced to refactor my code to match a library update. There's a good parallel here with boost::python vs. pybind11; there's always room for more and newer entrants, but most of them will not overcome the first-mover advantage.

On the boost front, I should have noted the difference between VMD [1] and boost::preprocessor [2]. I think VMD [1] trades some backwards compatibility for coherence and consistency and is a better starting point for new code.

[1]: https://www.boost.org/doc/libs/1_70_0/libs/vmd/doc/html/inde...

[2]: https://www.boost.org/doc/libs/1_76_0/libs/preprocessor/doc/...

Re: Macros on Steroids: How pure C can benefit from metaprogramming

#10
post #6

Earlier quoted context omitted.

If you need these kinds of advanced metaprogramming capabilities then I feel like that's a sign that maybe plain C isn't suitable for your project and you'd better off switching to Zig, Rust, D or C++. These all provide powerful compile-time execution capabilities and the ability to expose C interfaces.

Only if you can switch to something like Zig, Rust, etc. But a tremendous amount of code bases are already written in plain C. Using preprocessor metaprogramming allows you to invoke macros right in the same files in which you write ordinary C code, without the need for integration with other languages.

> Using preprocessor metaprogramming allows you to invoke macros right in the same files in which you write ordinary C code

C++ effectively lets you do this too. And Zig will let you import and compile C files seamlessly. I suppose you have to switch compilers, but that's not so different to adding the additional pre-processor compiler.

Post reply on HN