6 ms·
Show HN: Sum (algebraic) types for C in one 100 line header
- 3dworldrunner 2y agoCarcinization.
- feb 2y agoNice system built with only a couple of C99 macros. That small header also achieves matching for specific C types over the "sum types". In the context of C99, isn't tagged union the more usual name instead of sum type?
- chongli 2y agoIt's interesting but not very practical. It's an "algebra of types" with only constants, no variables, since C does not have type variables. Thus it misses much of the point of algebraic data types in a language like Haskell (deep composability and generics with very little code to write). Take one of the most basic sum types in Haskell's base library, Maybe: data Maybe a = Nothing | Just a This simple construction gives you the ability to write functions over optional values and avoid the issues with null pointers. This would be an amazing feature to have in C but it can't be achieved due to C's very limited type system.
- Hirrolot 2y agoI used to define `Maybe` in C as a macro over a tagged union. It really unveiled a number of logic errors at compile-time, but the issue of course is to use this kind of metaprogramming sanely. E.g., instantiating `Maybe` to some other macro `T(a)`, where `a` is some other (concrete) type, would already cause a headache.
- Gibbon1 2y agoI got to say adding type variables to C would be super duper. And to me actually feels rather C like as well.
- xurukefi 2y agoIt's a nice idea, but I don't think it adds enough clarity to the code to justify the messy compiler warnings and errors that this kind of preprocessor abuse will eventually cause.
- natsucks 2y agoQuestion: is C gaining in popularity? If so, why exactly? Are their good reasons to be using C in product development rather than more modern languages?
- Q6T46nT668w6i3m 2y agoI don’t know anything about trends but I still write some C because it’s widely supported across a variety of platforms.
- eknkc 2y agoI’ve started using zig for some stuff recently and it can include c effortlessly. Also with rust it is pretty easy to interact with c (well, you need unsafe and I guess for this particular case, bindgen would not be able to provide bindings). I would not reach to c libraries on many other platforms but recently I started using more c, just not from c..
- bluetomcat 2y agoIt looks like some cool new kids are rediscovering it, after more than a decade of pythonisation and javascriptisation of programming. You can have things that behave like values and actually reside on the stack, you can ask the operating system for more memory and you have static fixed-size memory which is allocated when the program is run. Good old procedures without the distractions of prototypal inheritance, variable hoisting, dynamic typing, coroutines, list comprehensions and lambda callbacks. It's probably a more relevant tool for a larger class of problems than many people imagine.
- jerf 2y agoThere are a large number of "C but better" options, where the direction of "better" varies. Examples would be Go, Zig, Rust, each a different "direction" of better, but generally better. Anyone thinking of trying this I would advise against going to C directly. The footguns are dangerous enough as it is and are arguably even more dangerous if you're coming from a more modern language that if you came at C directly. You don't need to go this far back in time to have these things. But I do strongly agree that anyone who has done nothing by dynamic scripting language development should pick up a modern static language and learn how to use it. I consider having at least one of each a basic tool in the well-rounded developer's toolkit. And if you're still running on 200x-era arguments about the advantages and disadvantages of static versus dynamic languages, as many people are, you're going to be pleasantly surprised by the modern static languages. But you won't be pleasantly surprised by C. Most of the arguments developed for static vs. dynamic in that era were really about dynamic versus C. They all still apply; C qua C has not moved much since then. (Maybe you could justify C as "closer to the metal" but in the modern era personally I'd recommend just going straight to assembly for orientation and a tour. You don't have to dive super deep into it to get the sense.)
- tempodox 2y ago+1. It cannot possibly be worse than the C++ `std::variant` blunder.
- jjdisn 2y agoHonest question: what's wrong with std::variant? I'm quite fond of using it. Sure it has trade offs like being empty by exception, but that's necessary if you don't want it to allocate. Also, pattern matching would be nice instead of std::get with visitor, but that's more of a language issue than an std::variant issue
- rwbt 2y agoEverytime I have to use std::get<> and std::visit<> I feel like the committee has failed all of us.
- TwentyPosts 2y ago> that's necessary if you don't want it to allocate. Wait, what does one have to do with the other?
- OskarS 2y agoI'm not totally 100% on this, but: valueless_by_exception happens when the move assignment operator throws (which should never happen in good C++, but is not disallowed by the language). That means, the variant used to hold value X, we were moving value Y into it, but the move assignment operator failed. What is now the state of the variant? It's not X, since we started running the move constructor, which could have started destroying the old value before throwing. But it's not Y either, because the constructor didn't finish. So what's the value that's being held? The answer is that there is no valid value. How could this be fixed using allocation? Well, if you assume that std::variant allocated, it could be implemented in such a way that the std::variant just held a pointer to a heap area which stored the actual contents of the value. When you move assign, you construct a new element on the heap and move into that. If the move assignment completes successfully, you swap the old value pointer for the new one and destroy the old value. But if move assignment/construction fails, you just retain the old pointer: nothing has been destroyed, and the variant still holds a valid value. This is very similar to the "strong exception guarantee" for std::vector, which is violated if the move assignment operator for the value throws. This is one of many reasons why the move constructor/assignment operator should always be noexcept: there's no reason why it should ever throw, and it violates a bunch of these kinds of guarantees. I think, anyway. I would be happy to be corrected if I got this wrong.
- danielspace23 2y agoI know it's a minor thing, but why does this link to GitHub? The repository is described only as being a mirror of a SourceHut repo, and the user's profile has a banner telling that he's part of the giveupgithub.org movement. Looking at this post's submitter username, I think OP is the one who owns the repository, so why do this?
- beryilma 2y agoI am confused. If the author is part of the Give Up GitHub movement, then why still keep 29 repositories on GitHub! Obviously, they didn't give it up.
- tpoacher 2y agonot op, but github serves two purposes: git mirror, and reputation/network effects. By relying on github for the latter while redirecting to another mirror for the former allows you to utilise github's reputational system to promote both your project AND the mirroring alternative.
- ackfoobar 2y agoSaw the title and thought "Didn't I just see C sum types in HN recently?" https://news.ycombinator.com/item?id=40307098 https://news.ycombinator.com/item?id=40307098 > Inspired by datatype99, but consisting of one small standard-conforming C99 macro-only header that is fast to compile.
- deleted 2y ago[deleted]