14 ms·
An Enum type has to be on the core Go team's radar by now. It's got to be tied with a try/catch block in terms of requested features at this point (now that we
by H1Supreme 2y ago
An Enum type has to be on the core Go team's radar by now. It's got to be tied with a try/catch block in terms of requested features at this point (now that we have generics).
- TwentyPosts 2y agoThe issue is that it's more or less impossible to graft onto the language now. You could add enums, but the main reason why people want them is to fix the error handling. You can't do this without fracturing the ecosystem.
- drdaeman 2y ago> but the main reason why people want them is to fix the error handling Why do you think so? Maybe I'm an odd case, but my main use case for enums is for APIs and database designs, where I want to lock down some field to a set of acceptable values and make sure anything else is a mistake. Or for state machines. Error handling is manageable without enums (but I love Option/Result types more than Go's error approach, especially with the ? operator).
- randomdata 2y ago> my main use case for enums is for APIs and database designs, where I want to lock down some field to a set of acceptable values and make sure anything else is a mistake Then what you are really looking for is sum types (what Rust calls enums, but unusually so), not enums. Go does not have sum types, but you can use interfaces to archive a rough facsimile and most certainly to satisfy your specific expectation: type Hot struct{} func (Hot) temp() {} type Cold struct{} func (Cold) temp() {} type Temperature interface { temp() } func SetThermostat(temperature Temperature) { switch temperature.(type) { case Hot: fmt.Println("Hot") case Cold: fmt.Println("Cold") } }
- blueberry87 2y agoannoyingly go can't have proper sum types, as the requirement for a default value for everything doesn't make any sense for sum types
- andyferris 2y agoYou can just default to the first variant, no?
- throwaway143829 2y agoCouldn't the zero value be nil? I get that some types like int are not nil-able, but the language allows you to assign both nil and int to a value of type any (interface{}), so I wonder why it couldn't work the same for sum types. i.e. they would be a subset of the `any` type.
- randomdata 2y agoSaid "requirement" is only a human construct. The computer doesn't care. If the humans choose to make an exception for that, it can be done. Granted, the planning that has taken place thus far has rejected such an exception, but there is nothing about Go that fundamentally prevents carving out an exception.
- throwaway143829 2y agoEnums and sum types seem to be related. In the code you wrote, you could alternatively express the Hot and Cold types as enum values. I would say that enums are a subset of sum types but I don't know if that's quite right. I guess maybe if you view each enum value as having its own distinct type (maybe a subtype of the enum type), then you could say the enum is the sum type of the enum value types?
- randomdata 2y ago> Enums and sum types seem to be related. They can certainly help solve some of the same problems. Does that make them related? I don't know. By definition, an enumeration is something that counts one-by-one. In other words, as is used in programming languages, a construct that numbers a set of named constants. Indeed you can solve the problem using that: type Temperature int const ( Hot Temperature = iota Cold ) func SetThermostat(temperature Temperature) { switch temperature { case Hot: fmt.Println("Hot") case Cold: fmt.Println("Cold") } } But, while a handy convenience (especially if the set is large!), you don't even need enums. You can number the constants by hand to the exact same effect: type Temperature int const ( Hot Temperature = 0 Cold Temperature = 1 ) func SetThermostat(temperature Temperature) { switch temperature { case Hot: fmt.Println("Hot") case Cold: fmt.Println("Cold") } } I'm not sure that exhibits any sum type properties. I guess you could see the value as being a tag, but there is no union.
- imetatroll 2y agohttps://www.postgresql.org/docs/current/datatype-enum.html https://www.postgresql.org/docs/current/datatype-enum.html Then wrap appropriately. Something like sqlc will actually generate everything you need.
- Kamq 2y ago> but I love Option/Result types more than Go's error approach The thing is, these don't add much on their own. You'd have to bring in pattern matching and/or a bunch of other things* that would significantly complicate the language. For example, with what's currently in the language, you could definitely have an option type. You'd just be limited to roughly an api that's `func (o Option[T]) IsEmpty() bool` and `func (o Option[T]) Get() T`. And these would just check if the underlying point is nil and dereference it. You can already do that with pointers. Errors/Result are similar. A `try` keyword that expands `x := try thingThatProducesErr()` to: x, err := thingThatProducesErr() if err != nil { return {zero values of the rest of the function signature}, err } Might be more useful in go (you could have a similar one for pointers). * at the very least generic methods for flat map shenanigans
- Mawr 2y agoUsing an Option instead of a pointer buys you the inability to forget to check for nil. Just need to make sure the Option exposes the internal value only through: func (o Option[Value]) Get() (Value, bool) { return o.value, o.exists } Accessing the value is then forced to look like this: if value, ok := option.Get(); ok { // value is valid } // value is invalid Thus, there's no possibility of an accidental nil pointer dereference, which I think is a big win. A Result type would bring a similar benefit of fixing the few edge cases where an error may accidentally not be handled. Although I don't think it'd be worth the cost of switching over.
- Hendrikto 2y agoHow is that better than if value != nil { // value is valid } // value is invalid ? Of course, this is often left out, but you can just as easily do: value, _ := option.Get() So this is just not true: > Using an Option instead of a pointer buys you the inability to forget to check for nil.
- Mawr 2y agoIt's better because you do not need to remember to check for nil, the compiler will remind you every time by erroring out until you handle the second return value of `option.Get()`. > Of course, this is often left out, but you can just as easily do: Unfortunately it gets brought up pretty much every time in these discussions. Deliberate attempts to circumvent safety are not part of the threat model. The goal is prevention of accidental mistakes. Nothing can ultimately stop you from disabling all safeties, pointing the shotgun at your foot and pulling the trigger.
- sethammons 2y agoWhen enums make it from the language to the db, things are now brittle and it only takes one intern to sort the enums alphabetically to destroy the look up relations. An enum look up table helps, but now they are not enums in the language.
- LorenzoGood 2y agoI just want regular enums, that would solve the problems that result from using the current status quo.
- jhoechtl 2y agoI would like to have proper stack traces. With that the error handling in go would be fixed.
- sethammons 2y agoYou can emit a stack trace anytime you like
- foldr 2y agoDepends what you mean by 'enums' exactly, but now that generics has been added, a small change would be to allow interfaces defined via type disjunction to be used as concrete types: type Option1 struct { ... } type Option2 struct { ... } type MyEnum interface { Option1 | Option2 } var myValue MyEnum // currently not legal Go That doesn't solve all the use cases for enums / sum types, but it would be useful.
- foobiekr 2y agos/fracturing/having to use older libraries in the existing manner/
- jurschreuder 2y agoI've never needed either. Try/catch is super confusing because the catch is often far away from the try. And in Python I just put try/catch around big chunks of code just in case for production. I think Go is more stable and readable because they force you not to use the lazy unreadable way of error handling. Enums I honestly never used in Go also not the not-type-safe ones. But I'm also someone who used interfaces in Go maybe I think 4 times only in years and years of development. I just never really need all those fancy things.
- kbenson 2y agoI think what this comment is missing is any sort of analysis of how your experience maps to the general go user, and an opinion on while you've never needed either whether you think it could have provided any benefit when used appropriately. For example, and option type with enums combined can ensure return values are checked by providing a compile time error if a case is missing (as expressed in the first few examples of the readme).
- jurschreuder 2y agoI know it can, the compiler can do one more "automatic" unit test based on the type checking system. But they decided not to add enums because it conflicted and overlapped too much with interfaces. I just want to add "my" experience that personally, yes maybe you can argue enums are nice, but I never missed them in Go. I personally agree with the Go team on how they argue and for me it would be a step back if they listened to the herd that does not take all sides of the story into consideration but just keeps pushing enums. Try/catch is just a really bad thing all "hacky solution" alarm bells go off for me if you want to change error handling to giant try/catch blocks.
- lelanthran 2y ago> But they decided not to add enums because it conflicted and overlapped too much with interfaces. I'm very curious now about how it might conflict and/or overlap with interfaces. To reach the goal of an enumeration type (and all the strong type-checking that that brings with it), enums could look as simple as: type DayNames enum { Sunday Monday Tuesday Wednesday Thursday Friday Saturday } ... func isFunDay (dow DayNames) { // This must fail to compile, because there is an unhandled enumeration switch { case Sunday: ... case Monday: ... case Tuesday: ... case Thursday: ... case Friday: ... case Saturday: ... } ... } ... isFunDay (0) // Compile failure var x int isFunDay (x) // Compile failure And I don't see how that conflicts or overlaps with interfaces.
- Thaxll 2y agoNo one wants try/catch/exception in Go.
- anacrolix 2y agoSpeak for yourself. Without decent error type handling, exception handling is inevitable.
- MathMonkeyMan 2y agopanic/recover/error?
- callc 2y agoComments like this are what drives me away from Go; comments that enforce a particular belief about how or what features you should or should not use/introduce in your PL. Talking in absolutes is so far removed from a logical arguments and from good engineering. I would appreciate if anyone could recommend a language like Go (static, strong typed, not ancient, good tooling) with a friendly community, that won’t ostracize the non-believers. Zig?
- AnonymousPlanet 2y agoGo is a very opinionated language from it's inception. We could probably argue for all eternity about code formatting, for instance. But Go went and set it in stone. Maybe it's part of good engineering to keep things simple and not allow hundreds of ways to do something. Maybe the people who use Go are the ones who just want to write and read simple and maintainable code and don't want it to be cluttered with whatever is currently the fashion. You could look at Lisp. It's kind of the opposite of Go in this regard. You can use whatever paradigm you like, generate new code on the fly, use types or leave them. It even allows you to easily extend the language to your taste, all the way down to how code is read. But Lisp might violate your set of absolutes.
- callc 2y agoThanks for your response AnonymousPlanet. I agree there is value in the pursuit of a minimal set of features in a PL which brings many benefits. And of course the opposite - an overly feature packed and/or extensible PL as a core feature has tradeoffs. Over this range of possibilities my preference probably falls somewhere in the middle. I see an effect where the languages whose primary goal is a particular set language design choices (such as strict memory safety over all else) grow a cult following that enforces said design choices. Maybe in the pursuit of an opinionated language, even if the designers are reasonable at the language's inception, the community throws out logic and "opinionated" becomes a in-group out-group tribal caveman situation.
- AnonymousPlanet 2y agoI am so tired of reading Java/C++/Python code that just slaps try/catch around several lines. To some it might seem annoying to actually think about errors and error handling line by line, but for whoever tries to debug or refactor it's a godsend. Where I work, try/catch for more than one call that can throw an exception or including arbitrary lines that don't throw the caught exception, is a code smell. So when I looked at Go for the first time, the error handling was one of the many positive features. Is there any good reason for wanting try/catch other than being lazy?
- slt2021 2y ago>the error handling was one of the many positive features. sounds good on paper, but seeing "if err!=nil" repeated million times in golang codebases does not create positive impression at all
- slt2021 2y agogolang keyboard ftw https://pbs.twimg.com/media/DCIF7-2W0AEAv9c.jpg https://pbs.twimg.com/media/DCIF7-2W0AEAv9c.jpg
- Mawr 2y agoYes but the impression is largely superficial. The error handling gets the job done well enough, if crudely.
- FuckButtons 2y agoThe ability to quickly parse, understand and reason about code is not superficial, it is essential to the job. And that is essentially what those verbose blocks of text get in the way of.
- Mawr 2y agoSure, I just don't think it's that significant. Humans don't read/parse code character-by character, we do it by recognizing visual patterns. Blocks of `if err != nil { }` are easy to skip over when reading if needed.
- mark38848 2y agoHow the fuck do you release a language without enums?
- sethammons 2y agoCan someone help me understand why enums are needed? They only seem like sugar for reducing a few lines while writing. What cannot be achieved without them or what is really a pain point they solve? Maybe it is hard to have a constant with type information?
- brainzap 2y agoThe original enum are just enumerated integer constants. What people want "the ability to express enums with an associated value", I think we should invent a new term.
- masterj 2y agoThe term you're looking for is ADT - Algebraic Data Types https://en.wikipedia.org/wiki/Algebraic_data_type https://en.wikipedia.org/wiki/Algebraic_data_type
- randomdata 2y agoWe did: Sum types.
- bouncycastle 2y agobecause you can just declare a custom type and have constants that use the custom type.
- hpeter 2y agoYou can enumerate constants. There is syntax to implicitly assign the integer values, just use iota as a value.
- Too 2y agoTo be honest I haven’t seen a single programming language that has decent enums. With that I mean fundamental and fool proof functions for to/from a string, to/from an int, exhaustive switch cases, pattern matching, enumerating. Seems like something that wouldn’t be too hard but everybody always fails on something.