6 ms·
At this point I always wonder why people who write stuff like this don't just move to a different language. You are introducing insane amounts of hidden complex
by rowanG077 1y ago
At this point I always wonder why people who write stuff like this don't just move to a different language. You are introducing insane amounts of hidden complexity(see also the other posts on that blog). For something that just exists in other languages. Or maybe this is just a fun puzzle for the author, in which case it's totally fine.
- throw-qqqqq 1y agoYou don’t always get to choose your language. Especially in the embedded/firmware area of software development, C is the most widely available option, if not the only option besides ASM shrugs
- rowanG077 1y agoDefinitely. I still don't think you should swim against the stream. Just bite the bullet and write idiomatic C. The people who will have to debug your code in the future will thank you.
- throw-qqqqq 1y agoI agree 100%
- windward 1y agoIt is, but the bar of what's considered too 'clever' in embedded/firmware is usually lower than this. In fact, even the ternary conditional operator is too much.
- fuhsnn 1y agoThe said library is a bit farther away from the C that is widely available. It relies on C23 features, GNU statement expression, GNU nested function, sanitizer runtimes, VLA types and a very niche pattern of sizeof executing its statement-expression argument; only platforms that provide latest GCC/Clang would be able to use this.
- uecker 1y agoIn the library I experiment with various things, and C23 and nested functions are not really required. And for running the code, it only relies on GNU statement expression. For bounds checking, you need need the sanitizers. Overall, it is still far more portable than C++ or any other new language.
- throw-qqqqq 1y agoFair point. I did not notice that. Most C-only compilers only support C99 or a subset thereof
- pjmlp 1y agoUnless you are talking about PIC and similar CPUs, there is hardly a modern 16 bit CPU that doesn't have a C++ compiler available as well, assuming that we still consider 16 bit modern for whatever reason. Heck I learned to program in C++, back when DR-DOS 5 was the latest version, and all I had available was 640 KB to play around, leaving aside MEMMAX. Nowadays the only reason many embedded developers keep using C is religous.
- uecker 1y agoReligion and the garbage code C++ compilers produces, incomprehensible error message, unstable tooling, and very long compilation times.
- simonask 1y agoWhat year is it, 1998? Am I going crazy? I think you're making some extraordinary claims. I'd love to see some receipts. :-)
- uecker 1y agoWhat specific claim do you think is extraordinary: That embedded programmers still often use C, that compilation times for C++ are often very long, that the languages is less stable than C, or that code produced by C++ can be worse?
- simonask 1y agoEspecially the last claim seems (that code generation for C++ is worse). It's the same compiler backend in all major compilers. Do you have any examples?
- throw-qqqqq 1y agoPurely guessing, but the "unstable tooling" could perhaps refer to the fact that C++ as a language has evolved a lot. I have had trouble compiling older C++ code bases with newer compilers, even when specifying C++98 as source standard. I gave up trying to get Scott McPeak's Elkhound C++ parser to compile, last I had to attempt it. C is a bit more forgiving on that topic (it hasn't changed as much, for better or worse).
- amiga386 1y agoQuite. There's standard POSIX behaviour for this. Divide by zero and execution continues, safely, in your SIGFPE exception handler.
- uecker 1y agoBecause the different languages suck much more.
- munchler 1y agoSo this was inspired by Haskell, but you don’t actually think Haskell is a good language?
- dazzawazza 1y agoOther languages internalise that complexity. C leaves it bare, human scale and understandable. The speed at which you can write great C code often far outstrips other languages which are applicable to the problem domain. All languages are a compromise, there are no silver bullets.
- uecker 1y agoBTW: I think what me annoys me about this comment is the claim that this would be "insane amounts of hidden complexity" . If you you look at the article, it four simple one-line macros: #define maybe(T) struct maybe_##T { bool ok; T value; } #define maybe_just(T, x) (maybe(T)){ .value = (x), .ok = true } #define maybe_nothing(T) (maybe(T)){ .value = (T){ }, .ok = false } #define maybe_value(T, x) (({ maybe(T) _p = &(x); _p->ok ? &_p->value : (void*)0; })) Please compare this to your other languages.
- rowanG077 1y agoWell yes I find these pretty insane. It's not ergonomic. It doesn't actually offer any safety. It has no integration with anything else. If I compare this to, for example, the rust Option, or Haskell's Maybe, it's not even funny how stark the difference is. And both of them are over the counter included. Especially the the safety is something I can't step over. I don't feel it offers anything substantial over just having the struct without these macros.
- uecker 1y agoPlease spell out your criticism exactly. Where do you see an issue with ergonomics? What exactly miss on integration? The safety property for such a type is clear: not being able to access the value when it does not exist. It does this. But most importantly before I let you shift the goal post: this was not original criticism. You said "insane complexity"
- rowanG077 1y agoBad ergonomics, no integration and safety are all thinks that lead to complexity you need to manage were you to actually use this macro. The macros themselves are simple. But I don't think it's wrong to say using the macros does introduce insane complexity. Such things are often the case in C. The language is simple. To write anything of substance you have to introduce, often high amounts of, complexity. 1. Ergonomics: Forcing the null sanitizer is quite a sledgehammer you often cannot, or don't want, to pay, You are forcing global behavior for something you really only want locally for this construct. A misuse of maybe_value is a crash where in other languages you have case/match and compile time errors. There is no type inference so you have to be explicit at every, single, line, that you really mean a maybe(int) or whatever. 2. Integration: No libraries uses this, meaning any usage is limited to your own code only. Requiring manual and error prone translation at every interface. 3. Safety: No check the null sanitizer is actually on. This is a huge footgun where someone thinks "I know I use this neat macro I saw here". And then of course not enabling the null sanitizer and everything breaks. So now for this to be safe it's not enough to understand the code. You need to check if the compile options are just right. This is especially insidious since this cannot be hidden in some object file where you make damn sure the sanitizer is on. the CONSUMER of this API must enable the sanitizer For these reason I would ban this macro in any code I have control over.