Live data from Hacker News

Algebraic Data Types for C99

github.com

141–150 of 233 posts

Re: Algebraic Data Types for C99

#141
post #130

Earlier quoted context omitted.

This is where I like to cite Dijstra's "Go To Statement Considered Harmful". What a lot of people miss about that paper is that he wasn't just talking about goto statements. He was also making a more general observation about how more powerful and general programming language features are not necessarily desirable, because they tend to adversely impact developer productivity. The reason I, as a user, prefer structure…

That's exactly where I am. Pattern matched sum types "feel great" to code in to an expert because they are a concise and reasonably tight way to express the otherwise boring "enumerate over possibilities" code. But they're hard to read for anyone who isn't an expert on not just the language but the type in question (c.f. Rust's Option() idioms all looks like line noise to newbies, etc...). And that's a bad trade. In…

Pattern matching on the "top level branch" of the ADT, whatever you call it, is pretty darned useful.

Pattern matching on the next level down is a power tool to be used with care.

Having used some pattern matching languages for quite some time, I find anything much deeper than that is a code smell at best and pathological at worst. Pattern matching creates coupling proportional to the depth/complexity/precision of the pattern match. The top-level coupling is often unavoidable; if you're pattern matching at all, you certainly care which "branch" you are on and there is likely no refactoring that away. But the danger rises rapidly the deeper in you go. It's just so easy to pattern match on a third-level part of the complex object when you really ought to be wrapping that behind a function somewhere, possibly itself emitting a sum type value.

... but if all you really need is that "top level" match, a lot of pattern matching syntax and features are not really necessary (if not positively dangerous).

Re: Algebraic Data Types for C99

#142
post #71
post #54

Earlier quoted context omitted.

Some have even older Java versions in 'prod'. 6 is still alive in some places out there, because management refuses to pay for either upgrade, replacement or dismantling. I have a mid-sized application I built on 17 that's used to deliver a particular project, really looking forward to finish the project so I get to move to 21 and refactor it with these new features and make it more general.

Oof, I didn't know that anyone still used Java 6 anywhere. I have to think that it's a potential security nightmare at this point isn't it?

Absolutely, so you try to seal it in hermetically, only talk to it over a special message bus or something.

Sometimes the upgrade path from 6 onwards isn't as nice as it usually is from 8 up, especially if you built with some old undead libraries that require an heroic effort to understand well enough to reimplement. Takes a very special organisation to divert some person-years to pull it off, and as some middle or other manager it's highly unlikely to catch you a new, better job even if it goes well.

Re: Algebraic Data Types for C99

#143

Could you not get most of the benefits of ADTs using structs + unions + enums? I've used the pattern where I had a union of several types and an enum to differentiate which one to pick. Something like std::variant seems to work a bit like a sum type. The only issue is you can't do a clean switch statement that matches on the specific value of a field, but nested switch statements aren't that messy.

The absolutely critical thing is to have checked every alternative when dealing with a sum type value. This is hard to do with macros, though not impossible (basically you'd need a macro to start a matching context and which introduces a variable in which to keep track of all the alternatives checked, then you need to arrange for the end of the matching context to check that all alternatives were checked).

Re: Algebraic Data Types for C99

#144

Could you not get most of the benefits of ADTs using structs + unions + enums? I've used the pattern where I had a union of several types and an enum to differentiate which one to pick. Something like std::variant seems to work a bit like a sum type. The only issue is you can't do a clean switch statement that matches on the specific value of a field, but nested switch statements aren't that messy.

> Could you not get most of the benefits of ADTs using structs + unions + enums? The modelling aspects can be simulated, yes, but that's barely half of the benefits of ADTs. Pattern matching is a big ergonomic benefit.

TFA gets pattern matching.

The critical thing is that the compiler (or macro system) needs to check that you've checked all the alternatives.

Re: Algebraic Data Types for C99

#145
post #82

Earlier quoted context omitted.

I can easily argue that people don't think in terms of boolean logic. For one, the evidence seems as strong that people generally think backwards from the answer far more than they do forwards from the ingredients. This is often why new things are so long to be discovered. It isn't that people couldn't have gotten there, but they didn't know to go for it. For two, addition is a wildly disparate thing everywhere we us…

> For one, the evidence seems as strong that people generally think backwards from the answer far more than they do forwards from the ingredients. Logic doesn't really have a direction, it works backwards or forwards. Even if you're solving a system "backwards", whatever that means, you still have to satisfy all of the necessary AND and OR constraints for a solution to be valid, so you're effectively still building A…

And this logic is how folks convince themselves that ball players are doing trigonometry when playing. It is just wrong.

You can /model/ it that way. But you are making a symbolic model to justify how a solution is reached.

Now, it can be frustrating to consider that this model could produce an agent that is better at the ball game than the players. But it is silly to think that means you have mirrored them.

Re: Algebraic Data Types for C99

#146
post #142
post #71

Earlier quoted context omitted.

Oof, I didn't know that anyone still used Java 6 anywhere. I have to think that it's a potential security nightmare at this point isn't it?

Absolutely, so you try to seal it in hermetically, only talk to it over a special message bus or something. Sometimes the upgrade path from 6 onwards isn't as nice as it usually is from 8 up, especially if you built with some old undead libraries that require an heroic effort to understand well enough to reimplement. Takes a very special organisation to divert some person-years to pull it off, and as some middle or o…

It makes me sad, but I totally understand why someone would stay with Java 6, for the same reason that there's still COBOL stuff hanging around: the stuff "works" as is, upgrading is expensive, and some business person decided that the cost of the upgrade isn't worth it for the value they'd receive.

I do worry that there's "Y2K-esque" bugs hiding in Java 6 programs somewhere. I don't think java.util.date uses 32 bit integers for time so the 2038 problem probably won't be an issue, but I do wonder if there's other stuff hiding.

Re: Algebraic Data Types for C99

#147

Earlier quoted context omitted.

That doesn't matter in practice. If two programming languages have the same underlying feature but one has syntactic sugar to make it very easy to use and the other does not (so is quite cumbersome to use) then you'll find that the library ecosystem for the former language will see the feature in widespread use whereas the ecosystem of the latter will tend to shun the feature. This is one of the social factors of pro…

Yes, features that are easy to use will be more often used, while inconvenient features will be less used. I don't quite see any controversy with my comment.

The point is that in both cases the underlying feature is present, so APIs will be compatible. However, the lack of syntactic sugar in the one case will make any API that uses the feature cumbersome to use in that language, so in practice it will be avoided.

Re: Algebraic Data Types for C99

#148

One of the crimes of modern imperative programming languages is not having ADTs (except maybe Rust) built-in. It is such a basic mental model of how humans think and solve problems. But instead we got inheritance and enums which are practically very primitive.

[deleted]

Re: Algebraic Data Types for C99

#149
post #141
post #130

Earlier quoted context omitted.

That's exactly where I am. Pattern matched sum types "feel great" to code in to an expert because they are a concise and reasonably tight way to express the otherwise boring "enumerate over possibilities" code. But they're hard to read for anyone who isn't an expert on not just the language but the type in question (c.f. Rust's Option() idioms all looks like line noise to newbies, etc...). And that's a bad trade. In…

Pattern matching on the "top level branch" of the ADT, whatever you call it, is pretty darned useful. Pattern matching on the next level down is a power tool to be used with care. Having used some pattern matching languages for quite some time, I find anything much deeper than that is a code smell at best and pathological at worst. Pattern matching creates coupling proportional to the depth/complexity/precision of th…

> Pattern matching on the "top level branch" of the ADT, whatever you call it, is pretty darned useful. Pattern matching on the next level down is a power tool to be used with care.

Which is exactly how Perl apologia arguments went.

Re: Algebraic Data Types for C99

#150

Earlier quoted context omitted.

> so you can't change the variant without creating a new instance. Isn't that true of ADTs in all languages? I can't think of a single language with ADTs that lets you change the tag/variant of an existing value.

In Rust [0]: #[derive(Debug)] pub enum Example { Foo(i32), Bar(&'static str), } let mut ex: Example = Example::Foo(42); println!("{ex:?}"); // Foo(42) let ex_ref: &mut Example = &mut ex; *ex_ref = Example::Bar("hello"); println!("{ex:?}"); // Bar("hello") Given a mutable reference to a value of enum type, you can replace it with another variant. Or you can swap it out with any other value of the same type, even if th…

This doesn't have anything to do with ADTs. It's because Rust has both in-place variables and references. You aren't changing the variant of an existing ADT, you're replacing the entire ADT value with a new one. That replacement is visible in multiple places because the language allows you to take references to variables (the `&mut ex` expression).

You can accomplish the same thing in C and C++ because they also have in-place value semantics and allow you to take the address of any variable. You can't do that in Java only because Java doesn't let you take references to variables.

Post reply on HN