Live data from Hacker News

Go Enums Suck

zarl.dev

71–80 of 244 posts

Re: Go Enums Suck

#71

>>> But what you notice here is we have no string representation of these Enums so we have to build that out next, for this I just use a map[Operation]string and instantiate this with the defined string constants. Cries in I18N...

Or just define the constants as string constants in the first place: "type Operation string"

Re: Go Enums Suck

#72
post #13

A thing that so many enum solutions miss is that you have to have a path for a value outside of the current definition, or you lose a lot of flexibility in compatibility with any data that crosses wires or disks. Sounds fine for a lot of cases, of course, but in a world of mixed deployment fleets working on data, you pretty much have to have a way to allow a value that is not part of your current definition, or you a…

>> Sounds fine for a lot of cases, of course, but in a world of mixed deployment fleets working on data, you pretty much have to have a way to allow a value that is not part of your current definition, or you are basically placing a "poison pill" on your system.

I had the joy of a numeric ID (an int) getting a B added to the end of it to distinguish the product as being the "same" but sourced from another vendor... (and vendor is part of the system so this is layers of silly, but useful on the floor if there is a problem).

This is the down side of "fleets" of applications with differing degrees of type safety working in concert.

Should an enum be fixed, and its change need to be reflected in every system? Cause current go out of the box isnt that. Should it be open ended as your suggesting ... because a "new int value" can flow through the system in an "Unsafe" way depending on the permissiveness or quality of your code.

I dont like any of the answers, but I candidly dont have a lot of problems with the current enum system in go. Is it great, no. But if your validating at your borders/boundries (storage, api, etc) and being responsible I dont really give it much thought.

Re: Go Enums Suck

#73
post #36
post #20

Earlier quoted context omitted.

In what sense? Because they only apply to non-primitive types?

I'm assuming because of erasure? In C#, List and List follows the same assignment rules as T and U, and at runtime are represented by distinct types. That means that going from List to object to List causes a runtime error at the point of casting. In Java, every generic type is erased to object at runtime, so the runtime type is just List, and you could cast List to object to List and only get an error later, when yo…

The delayed error happens only when you ignore unchecked warnings, which would have been compiler errors if not for backward compatibility. One can turn them into errors with `-Werror`.

The type erasure has occasional benefits, like allowing objects that are polymorphic in their type argument when that’s still safe semantically (a simple example being emptyList() and emptySet()), where the type system isn’t expressive enough to otherwise allow it. This is a bit like the “unsafe” escape in other languages.

Re: Go Enums Suck

#74

Earlier quoted context omitted.

> Rust's enums are great. Rust doesn't have enums. It has sum types – that for some reason it arbitrarily decided to call enums. Sum types are great. There is a good case to be made that Go would benefit from the addition of sum types. But until that day there isn't much more you can do with enums. That's all enums are – a set of named constants.

I've heard this before, but I have a struggle understanding the abstraction. I make heavy use of rust and Python enums (Are they both misnamed?) Those + structs are generally the base of how I structure code. The "enums" in the article also seem to be of the same intent. Is this a "no true Scotsman" scenario? Some research implies the difference is a True Enum involves integer mapping, while a Sum Type is about a typ…

Enumerations back to integers. Enumerations can have iterators written on them that exhaustively enumerate the possible values. (Sum types either have no such enumeration at all, or in general, they're useless, so you don't see them.) Enumerations can be represented by a canonical and small set of strings, if you want a string backing them.

This is what an enumeration is, partially because that's precisely what the word "enumeration" means; the ability to assign an ordinal number to each value in the enumeration. To "enumerate" a set is to assign integers to them. In Python, for instance, see the "enumerate" function, which does exactly enumeration on the output of some iterator.

Sum types can be used to represent enumerations, but it's very restrictive subset of sum types. Trying to understand what a "sum type" is through the lens of a single integer would be a very strange way to approach them. Nor are sum types a "superset" of an enumeration; a base sum type is not an enumeration. You need to add more things to it to get an enumeration. In a Venn diagram they're the classic two cicles with some overlap in the middle but with distinct bits on each side.

I do not understand the strangely active desire some people seem to have to erase the distinction between these two things, as if some advantage will result, as if sum types will somehow become more useful than they are or as if they will somehow lose their abilities if we don't also call them enumerations. There is no advantage to smudging these two unique things together. Not saying that you are promoting this per se, the__alchemist, just that I've seen it a lot and I don't get it. It's like someone wanting to claim that database and files are really the same thing; well, sure, there's some overlap, but each does many things the other doesn't and trying to squint until they actually are the same thing is generally the exact wrong direction to go to attain understanding.

To put it another way, when adding an "enumeration" into a network protocol, you allocate some fixed number of bits to hold a given sized integer. When you add "a sum type" into a network protocol, you have a lot more work to do in general.

To put it yet another way, enumerations have meaningful implementations of a ".Next()" that a sum type really doesn't. If you have a sensible implementation of a given method on one type of thing and it's not sensible on some other thing, then clearly they can not be the same thing.

(I say multiple times that a sum types doesn't have such an implementation in this message. By that I mean that while it is trivial to have a "data Color = Red | Green | Blue | RGB Int Int Int" and implement an iterator to walk through all possible values, it is not something that is generally done for all sum types, and if the sum type also includes functions or other complex values it isn't in general possible at all in common programming languages. Again, writing an interator for "all possible functions" is perfectly theoretically possible, but in engineering terms not something anyone would actually do. All enumerations can be iterated.)

Re: Go Enums Suck

#75
post #5

I love Go. Especially how the devs stubbornly refuse to learn anything from Java, but stumble boneheaded into everything that Java solved over the years. Generics? We don't need that .. (time goes on) .. okay, damn it. Here! Generics! Enums? We don't need that, just do iota/integers! How long will it be this time until the Go devs accept that Java Enums are a safer and better abstraction over integers for the cases w…

You cannot expect to get the Turing award for just creating a language that uses stuff already known and just changes the syntactic sugar.[1]

To be explicit though, this comment is spot on. As someone who was part of the original Java development group when it was called "First Person Inc", I found the language "equivalence" concept debates the most interesting. For example, is Boolean a first class type? Or is it just a one bit integer? Is integer always signed? If you have 1 bit integers, 8 bit integers, 16, 32, and 64 bit integers, why not make 1024 bit integers a type too? Why is the number of bits fixed? If you want to be super radical, is it bits in an integer or is it digits? Is the integer type (radix, digits)? At one time there were discussions about real (signed), integer (unsigned), frac (fractional) and float (split).

And then a product manager type walks in and says something like "Love the architectural purity y'all are going for here but nobody else uses all these things so let's not make something that is so complicated we'll never ship it."

The author does a good job of exploring the characteristics of "good" enums, and I think it would be even better if it was understood that if your language is going to be used to implement finite state machines (which most programming languages do) then having strong protections against injecting invalid states into those machines is essential. If the language provides a way, that is great, otherwise you end up like the author did generating 30 - 50 lines of code for something that should take 3 - 5 lines to express.

[1] This is an inside joke, IYKYK

Re: Go Enums Suck

#76

> Anywhere that accepts an Operation Enum type will just as happily accept an int. This is a real pain as it almost completely negates the work we have done here. Is this a real problem? If there's a function signature that accepts `Operation`, the caller must explicitly cast the `int` to `Operation`. At that point, it's the caller's own fault. So I'm not really following what this is solving. As demonstrated in the…

> Is this a real problem? If there's a function signature that accepts `Operation`, the caller must explicitly cast the `int` to `Operation`. At that point, it's the caller's own fault.

You would think that, but that isn't always the case: https://play.golang.com/p/Ze3pfNEVTVs

It's very easy to create an enum value that isn't actually in the defined range

Re: Go Enums Suck

#77

It has always been surprising to me how primitive Go really is, for no really good reason. I understand the evolution of C, it made perfect sense back when it was invented. And the limitations were necessary due to the wide array of architectures and extremely limited computers of the time in every dimension (CPU speed, IO speed, RAM size, disk size, etc). Many of those dimensions have been improved by several orders…

Very disappointing.

Disappointing it maybe but productive it is not considering people can easily move to far better languages.

Re: Go Enums Suck

#78
post #10

Go's iota is probably one of the worst ideas in all programming languages. Not a full typesafe enum type, the same clunky "enums" (assigned constants) available in C, but they bother to implement an auto-incremented counter. So you can't depend on the enum for exhaustiveness warnings e.g. on switch statements, type checking, or correctness, but you do get a useless numeric association autogenerated with iota - so tha…

> Go's iota is probably one of the worst ideas in all programming languages.

iota is a great idea, especially if you have to define bit mask constants, e.g. 1 << iota. I wish other languages (yes, also those with enums) had it as well.

Re: Go Enums Suck

#80

> Go doesn’t technially have Enums and it is a missing feature in my book but there is a Go idiomatic way to achieve roughly the same thing. Oh, so it's a lot like Python then. > This is fine however it is nothing but an integer under the covers this means what we actually have is: Oh, so it's a lot like C++ then. > But what you notice here is we have no string representation of these Enums so we have to build that o…

Go is in this weird middle ground where it's modeled after C, so it's got things like no enums, return codes for errors, mutable everything, nulls, and pointers (that don't support arithmetic, so it's really just this "*" sigil that you have to remember to use sometimes), but it's also fully garbage collected and has built-in, stackful green threads. I have no idea what it's actually trying to be.
Post reply on HN