3 ms·
I wonder if go ever will get some sort of enum type? Or if int/string based types will be the goto way?
by asabla 2y ago
I wonder if go ever will get some sort of enum type? Or if int/string based types will be the goto way?
- stpedgwdgfhgdd 2y agoIf there is one thing that I find missing is proper enum support in the Go language. There are quite a few subtle caveats you can run into without proper support in the language like the article mentions. (E.g. Using iota, passing in an undefined enum)
- ramon156 2y agoThis might be a very simple and ignorant thought, but I'd be fine if they completely worked the same as Rust's enum's. [if let] is such a powerful feature, along with match arms.
- CraigJPerry 2y agoThat’s not an enumeration like the parent and grandparent are discussing (think of a collection of consts), that’s a tagged union you’re talking about. Confusing because rust used the name enum in their syntax for this (Haskell calls it data - well, Haskell uses data in their syntax for both product and sum types).
- tialaramex 2y agoWhat we're discussing here is always an actual sum type though, it's just a question of whether you're interested in half-assing it, and Rust is not. There are people who want C's "surprise it's actually just an integer" which lets them use C's enums as bit flags, and that I agree isn't just a sum type, but the fact that Rust will let you sum things which aren't units isn't that this is "really" a tagged union, that's a possible implementation detail but not the core idea. This is not C++ std::variant which really is just a tagged union. Option<OwnedFd> isn't a tagged union, it's "just" much nicer sugar for C's signed integer type. Option<&str> isn't a tagged union it's sugar for a fat pointer which can be null. And so on.
- klabb3 2y agoRust got those basic type system and pattern matching things so incredibly right it’s not even funny. I even like Go more for other reasons but I still cringe every time I have to use the error prone hacks mentioned in this post. Not to mention the largest source of noise: `if err != nil`, which Rust solved so elegantly using partly their enum types.
- tialaramex 2y agoSure, but "the same as Rust's enums" including a mention of pattern matching, is a really big expenditure on the novelty budget from the point of view of Go. What Rust does there is perfectly normal... for an ML. But before Rust you didn't really see an ML down there counting CPU cycles, so this wasn't even on the radar when Go was invented. I think to do that you'd probably give up a lot of the simplicity Go is aiming for. I personally think that simplicity is somewhat illusion (Amos' "I want off Mr. Golang's Wild Ride" https://fasterthanli.me/articles/i-want-off-mr-golangs-wild-ride https://fasterthanli.me/articles/i-want-off-mr-golangs-wild-... says it better than I could) but we should be clear that it's not that Go aimed to do what I want and missed but that it was never interested in that at all. An F1 car doesn't want to be useful for taking the kids to school, so it's silly if we're scoring it poorly for lack of child seat fixtures.
- masklinn 2y ago> Sure, but "the same as Rust's enums" including a mention of pattern matching, is a really big expenditure on the novelty budget from the point of view of Go. Following the addition of type sets for generics I think go actually has all the pieces for union types already and it’s a matter of putting them all together at the compiler level: - allow type sets as types (currently they’re only valid for constraints), probably excluding those using “underlying types” - implement match completeness for type switches over type sets And there you go, you’ve got unions from which you can easily implement sums via type declarations: type Foo int type Bar struct {} type FooOrBar interface { Foo | Bar } func Thing(v FooOrBar) { switch vv := v.(type) { case Foo: // you have a foo case Bar: // you have a bar // a default case is required if the cases are not exhaustive, forbidden if they are } } Is this perfect? Not even remotely, this suffers from the usual Go issues of zero values, unenforceable constructors, and nil interfaces. But these are issues of the language, they should be fixed in the language in a hypothetical Go 2, I don’t think there is a good reason to try and work around them here. Also completeness requirements could probably be extended to all “trivial” switches (types or values, not generalised expressions) via a go.mod stricture, similar to the new loop semantics.