12 ms·
Go Enums Still Suck
- perbu 3y agoI'm wondering if it be better if an iota would assign random, unique numbers at compile time, just to make it clear that these are not entirely safe identifiers inbetween compilations.
- datascienced 3y agoIf only there were a way in computer science to guarantee you couldn’t misuse a value. Then you wouldn’t need to rely on using UB to scare people into not making a mistake. (A dig at Go not your comment :-)
- logicprog 3y agoYeah, if only there were decades of programming language design research and field testing since C for Go to draw on...
- foldr 3y agoIota does have other uses where this behavior wouldn't work, such as for defining bitmasks: const ( Flag1 = 1 << iota Flag2 = 1 << iota Flag3 = 1 << iota ... ) The magic const shorthands even let you omit the explicit definitions for everything after Flag1, but I think it's easier to get the idea when all the definitions are explicit.
- neonsunset 3y agoOr, you know, it could learn a thing or two from C# enums (which are not even that good): [Flags] public enum Options { Default = 0, Option1 = 1, // can also be defined as 1 << 1 Option2 = 2, // can also be defined as 1 << 2 Option3 = 4 // can also be defined as 1 << 3 } The above is a choice, and an enum can be defined normally if it's not a bitmask. .ToString() would even format it correctly if multiple flags are toggled, it can be easily parsed with Enum.Parse<MyEnum>(text) and more. And hell, this is just tolerable implementation. It makes a lot of sense given historical context of C enums, which it's a direct improvement over, but not a step away in what is now considered to be the right direction represented by Rust enums instead. (Luckily, unlike Go, C# allows to trivially define Result<T, E> class/struct and a method on it in the form of Map(ok => .., err => ...))
- foldr 3y agoI don't think my comment ought to be the trigger for a generic rant against Go enums (or lack thereof). I was just pointing out a motivation for iota to increment in sequence from zero (rather than assigning a random unique value, as OP suggested).
- neonsunset 3y agoYou are right. Please don't take my criticism of a bad language to be a criticism of a perfectly reasonable comment :)
- masklinn 3y agoC# enums are strictly worse: they’re C enums, meaning they’re no safer than integers, but they don’t tell you about that. Go at least does not pretend it has anything like enums or sum types, and that is to its credit. You create a Go integer type, it’s flagrantly shit, but it’s not subtle about it.
- neonsunset 3y agoC# enums explicitly tell you that and it is well documented. You have easy Enum.IsDefined(enumValue) as well as Enum.GetName(enumValue) which work exactly as advertised. Switches on enum values will tell you to handle the default case too. They are not ideal by modern standards when you look at Rust. But to state that they are worse than Go's is a new and I can't find a way in which this kind of statement would defensible.
- ergonaught 3y agoI see literally nothing in this post that elaborates on "Go Enums Still Suck".
- axitanull 3y agoThe first sentence literally points out that the post is a continuation of previous post that elaborates on why Go Enum sucks.
- Brian_K_White 3y ago...and then does not show in what way they still suck. Or was it just very dry and although the text did not say so explicitly, the examples did some how show go enums in the act of sucking?
- deleted 3y ago[deleted]
- Alifatisk 3y agoWhat's up with the horizontal scroll?
- dewey 3y ago[flagged]
- bowsamic 3y ago[flagged]
- bheadmaster 3y ago[flagged]
- axitanull 3y agoIt just dawns to me that "complaining about the style or minor usability of the website" is a type of bike shedding that happens regularly in hacker news. Instead of contributing to the discussion related to the post, it's easier to just go "the website sucks."
- ayhanfuat 3y agoI don't think it is a minor annoyance. It is indeed very hard to read.
- axitanull 3y agoSo to continue our bikeshedding: Hacker News has no shortage of resourceful people that can silently handle the issue by themselves (the first comment even said themselves that they could simply use Reader Mode!). But the main point of my reply is: look at the number of replies that focus on the style of the website, and compare that to the number of replies that focus on the point of the post/article.
- randomdata 3y agoThere is no point to the article, though. Enums suck in every language that have them. There is good reason why many modern languages don’t have them at all, offering sum types instead. It doesn’t add anything to the conversation.
- kaba0 3y ago[flagged]
- leosanchez 3y agoPersonally I dislike go because of its type system. But I can see why people like it.
- bayindirh 3y agoIt's a simple, minimal language which does a lot of things right. I see it as a better C when you don't need to touch hardware or OS kernel. It's great for writing small utils, or doing multithreaded things in general. I don't understand qualms against programming languages. It's a tool. Best one is chosen for the task at the hand and applied to the problem. That's all.
- kelnos 3y agoSure, and some tools are better and worse than others. That's of course a subjective matter of opinion. I personally like things with stronger type systems than golang (and C) has to offer. If I'm going to write a small util and don't care so much about types (or performance), I'll reach for python. If I do, I'll reach for rust. Golang just never seems like the right tool for any of my jobs.
- bayindirh 3y agoUnderstandable. For what I do, Python is slow, and deployment is a problem (mandatory virtualenvs, etc.). I used to love Python, but Go replaced it immediately, I may say. If I need speed, I use C++. If I need something more complicated than a bash script, I use Python.
- neonsunset 3y agoThis comment is an easy tell. It's so prevalent. Because no one looked at how Go works, what Go does and what its overhead is. Not even mentioning, rightfully pointed out, a complete joke of a type system that completely disregards any improvements made since 80s.
- cupofjoakim 3y agoI'm having some real issues with legibility on this page. I'd like to encourage the author to decrease the font size, increase the line spacing and look into a smaller max-width for the paragraphs. It'd also be nice to have some spacing before a new sub-heading. I'm coming from a 4k screen, so that does play into it, but i honestly just could not read the article without changing the text properties here.
- chimeracoder 3y ago> I'm coming from a 4k screen, so that does play into it, but i honestly just could not read the article without changing the text properties here. It's not just using a 4K monitor. It's very difficult to read on mobile as well (and even harder to change properties there, short of reader mode).
- deleted 3y ago[deleted]
- kubb 3y agoIt would be a very significant improvement to have tagged unions in the language.
- dgb23 3y agoWhen I played around with zig, I got a much better understanding what they actually are and how they are (or can be) represented in memory. It's a language that lets you actually feel what your program is doing.
- otteromkram 3y agoYou didn't seem to be criticizing C#, though?
- kubb 3y ago??
- Sharlin 3y agotype planet int // Gravity[float64],RadiusKm[float64],MassKg[float64], ... Sorry, but what? Is this really an ad-hoc DSL embedded in a regular comment that's then preprocessed by… something, to generate the actual Go code? Certainly there's something that sucks here! Edit: I'd find it marginally less sucky if there at least were some special prefix like `//#` or `//my-preprocessor` or whatever to mark magical semantically significant comments. And what's the deal with the `field[type]` syntax that seems totally ad hoc, why not use the standard Go syntax `field type`?
- kelnos 3y agoYes, I think it's actually a decent way of doing it, given how limited golang is when it comes to enums. (Better might be to use tags, but I think they are only allowed on struct fields.) I think codegen is generally fine for repetitive tasks. It's just a shame that golang doesn't give you a way to do this built-in. Even java has this feature, even if it's lacking in some regards.
- rob74 3y agoNot sure if I understand you correctly, but Go has had a built-in way to do codegen for 10 years now: https://go.dev/blog/generate https://go.dev/blog/generate
- xienze 3y agoThere’s a history of this sort of faked annotation thing in Go. The most notable example being comments used to denote how a struct’s fields are mapped to/from JSON.
- kelnos 3y agoThe struct field tags thing (which are not comments) is at least something built into the language, that other code can access via reflection. Not being able to do this for this use-case, and having to rely on comments that are preprocessed by a code generator, is just a shame.
- Sacro 3y agoGo doesn't have enums.
- randomdata 3y agoIt doesn't have what Rust mistakenly calls enums - what everyone else in the world calls sum types, but it most definitely has enums in the traditional sense. Enum normally refers simply to assigning a number to something. That is what iota does.
- pjmlp 3y agoEnums in the traditional sense, is what Pascal and C have been doing it for decades. (* Pascal in 1970 *) Planet = (Unknown, Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune); // C in 1989 enum Planet {Unknown, Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune}; Plus type system guarantees, and in Pascal's case, run time capabilities to query enum values and ranges. Go's hack has barely anything to do with that.
- randomdata 3y agoYes, those examples too assign a number to something. Enumeration is not a new concept. In fact, it's an incredibly old concept that emerged in programming langauges as a hack to work around our, a the time, limited understanding of type systems. A modern type system has no reason for enums at all. Of course, Go purposefully tries to be an 'old' language, hence why it copied the antiquated pattern of providing assignment of numbers as a language feature.
- pjmlp 3y agoYou mean it copied how programming used to be before 1970's. Great achievement.
- randomdata 3y agoNot really. Enums as a programming language construct are a 1970s invention. Funnily enough, Algol 68 had sum types, although controversially so due to overhead concerns. If only Go had copied the state of programming before 1970, then we wouldn't have to listen to all the nonsense about enums sucking. Of course they suck – they are, and always will be, a hack to work around a limited type system.
- baby 3y agoGolang doesn’t have sum types is Golang’s biggest problem, not generics
- klabb3 3y agoYup. I love Go but they didn’t get types right. The level of abstraction is too low, and embedding and iota never feel quite right. Rust got the basics right. Pattern matching, no nulls, traits, sum types, and the sugar around try with the ?-notation is also great. Despite it all, this is not a dealbreaker, and Go shines for striking a great balance of a sensical language. But I always cringe a little inside when fanboys defend even the most awkward and annoying aspects of Go.
- dist1ll 3y ago> embedding [..] never feel quite right. funnily enough, I would argue that struct embedding is one of the things that Go actually got right. It's simple and elegant, and I think it could've been a useful addition to Rust.
- klabb3 3y agoYeah to be fair I don’t think I even have a problem with embedding per se. It’s quite nice. It’s more the fact that embedding can be used to work around missing type system features. I can’t recall exactly, but I remember using embedding for things that it probably wasn’t designed for, because it would save me a ton of boilerplate.
- dontlaugh 3y agoAlmost every single case of embedding I've encountered was buggy in some way. Explicit composition is much more reliable.
- lamontcg 3y agoIf someone autogenerates one way or another all the delgation, then that's just as buggy as embedding. The presence of all the explicit composition in the codebase doesn't mean that anyone actually sat down and thought about it all.
- sethammons 3y agoI see it a lot: there is a type of developer who loves brevity in writing of the code. It is critical to them. They believe that productivity is hurt with more verbose code. They optimize for writing. Depending on the project, maybe that is ok. I work on projects with multiple teams and zounds of developers. In this sphere, productivity is NOT increased with these kinds of things as they save moments during writing but cost more during onboarding and reading. The more you have to keep in your head to make the code make sense, the harder it is for new team members to spin up. Productivity in the kinds of orgs I work in is improved when individuals can look at a small section of code and understand it directly. If you are going up call chains to understand things, you are costing productivity. When you have to slow down and mentally parse something, you are costing productivity. I would take a hand written and hand maintained version of what this utility has as output over the utility every single time.
- ikari_pl 3y agoThe more code I need to READ to understand what I'm looking at, the less optimized for maintenance it is. If it takes 5 lines to understand that the map I'm looking at is effectively used as a set, it's worse than if I had a Set abstraction. Of course now I do, 20 of them, because when there's no built in, there will be packages made by the community.
- sethammons 3y agoCongrats, you just inherited this code and have to fix it: Mercury 0.378,2439.7,3.3e23,57910000,88,0.0000000001,0,false There is no way to infer what any of the values are. They are practically magic numbers. How do you know if you swapped a pair of numbers there and what that will do to the application? You have to mentally map all those things. It is vastly, overwhelmingly more new-dev friendly to use: MERCURY: Planet{ planet: mercury, Gravity: 0.378, RadiusKm: 2439.7, MassKg: 3.3e23, OrbitKm: 57910000, OrbitDays: 88, SurfacePressureBars: 0.0000000001, Moons: 0, Rings: false, },
- 3y ago
- jjice 3y agoI went years without using a language with sum types and was fine. As soon as I was exposed to them, I was hooked. They just make so much sense in so many places, especially in trees. It seems that over the past five or so years, they've been adopted more as pattern matching has. If they're not an explicitly feature of the language, then they can be replicated (like with Java sealed classes). I'm not sure if Go would ever implement them, or add something that we can more easily replicate sum types with, but god damn are they my favorite language feature that so few languages properly support. I wouldn't have expected Go to implement them, but after generics and range over functions, I feel like anything could be game.
- rightbyte 3y agoA nullable pointer is a sum type and Go has them.
- pjmlp 3y agoGo doesn't need to go full speed on sum types, plain basic Pascal enumerations from 1970 instead of that hacky iota/const dance, would be a huge improvement already.
- randomdata 3y agoThere is no practical difference between enums in Pascal and Go. What is different is that Pascal added an additional layer over enumerations – what is basically a poor man's sum types – to hide that there are enums under the hood. In fact, one has to perform an explicit conversion if they want to access the enum. Sum types predate enums, and no doubt they were trying to stay close to sum type semantics without the overhead. Something later languages, like C and Go, chose to forego in favour of exposing the enums naturally. But if you're going to go to all the trouble of implementing a poor man's sum types, why not just do it properly? It's not 1970 anymore. We've solved the overhead problems. Sum types are perfectly viable these days.
- pjmlp 3y agoOf course not, first Go would need to actually have support for proper enumerations. Go neither has the 1970 Pascal enumerations, nor the 1976 ML sum types. Both approaches too advanced to implement on 2009, apparently. We don't want the poor minds Go is targeted at, as per Rob Pike's words, to have imposter syndrome learning the language. As it is, is a non starter to even bother.
- coxley 3y agoWhat enums?
- pjmlp 3y agoMeanwhile in the 1970's.... type Planet = (Unknown, Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune); PlanetContainer = record gravity: real; radiusKm: real; massKg: real; orbitKm: longint; orbitDays: integer; surfacePressureBars: real; moons: integer; rings: boolean end; var planets : array [Planet] of PlanetContainer;
- nurettin 3y agoand const PlanetIndex = 1..9; Innersolarsystem = Mercury..Earth;
- Thaxll 3y agoIn most languages enum suck, it's not specific to Go, lot of pitfall and ABI issues, even my modern languages like C# have those.
- randomdata 3y agoYes, enums fundamentally suck. There is nothing you can do in a language to make them not suck other than to get rid of them... ...which, indeed, is quite viable as enums are just a hack to work around a limited type system anyway.
- deleted 3y ago[deleted]
- benreesman 3y agoI have a mountain of respect for Bell Labs and its contributions to the public welfare, and a lot of respect for the current group of alumni, mostly at Google, and mostly affiliated to a greater or lesser degree with golang. I have my differences with one or two of them (Pike telegraphs a wildly overcompensated imposter syndrome, but he’s almost as much of a genius as he acts like he is and who am I to judge on an overcompensated imposter syndrome, moreover when the guy in at the next desk over is Ken Thompson, who wouldn’t be a little intimidated by the legend). With that said, golang is too opinionated for its level of adoption, too out-of-touch with emerging consensus (and I’m being generous with “emerging” here, the Either monad is more than an emerging consensus around the right default for error handling), and too insular a leadership to be, in my personal opinion, a key contender outside some narrow niches. I’m aware that there are avid advocates for golang on HN, and that I’m liable to upset some of them by saying so, so I’m going to use some examples to illustrate my point and to illustrate that I’ve done my homework before being critical. Many, including myself, became aware of what is now called golang via this presentation at Google in 2007 (https://youtu.be/hB05UFqOtFA https://youtu.be/hB05UFqOtFA) introducing Newsqueak, a language Pike was pushing back in the mid-90s with what seems to be limited enthusiasm no greater than the enthusiasm for its predecessor Squeak. Any golang hacker will immediately recognize the language taking shape on the slides. I’ve been dabbling with golang for something like a decade now, because I really want to like it. But like a lot of the late labs stuff it seems to have suffered from the dangerous combination of the implications of Richard Gabriel’s Worse is Better observation: it was simpler, faster, cheaper, and ultimately more successful to incrementally adapt innovations from Plan9 into Linux (and other Unices), to adapt innovations from sam and acme into nvim/emacs (and now VSCode), and to adapt channel-based and other principled concurrency from Newsqueak/golang (not to mention Erlang and other more full-throated endorsements of that region of the design space) into now countless other languages ranging from things like TypeScript and Rust at the high end of adoption all the way to things like Haskell at more moderate levels of adoption. Ironically enough, the success of UTF-8 (a compromise for the non-ASCII world but the compromise that made it happen at all) is this same principle in action via the same folks! And golang would be fine as yet another interesting language serving as a testbed for more pragmatic applications of radical ideas: but it’s got corporate sponsorship that puts Sun Microsystems and Java to shame in scale and scope, but done quietly enough to not set off the same alarm bells. The best example of this is probably this GitHub issue: https://github.com/golang/go/issues/19991 https://github.com/golang/go/issues/19991 (though there are countless like it). I’ve worked with Tony Arcieri, he’s brilliant and humble and hard-working and while we haven’t kept in touch, I keep an eye out, and he’s clearly passionate about the success of golang. But proposal after proposal for some variation of the Either monad has died on procedural grounds for nearly a decade, all while being about the only thing that everyone else agrees on in modern industrial PLT: TypeScript supports it, Rust supports it, C++ de-facto supports it via things like abseil and folly, and of course the hard-core functional community never even bothered with something worse in the modern era. You can even kind of do it, but there are intentional limitations in the way generics get handled across compilation units to ensure it never gets adopted as a community-driven initiative. Try if you don’t believe me (my golang code has a Result type via emacs lisp I wrote). Another example is the really weird compilation chain: countless serious people have weighed in here, I’ll elide all the classics because most people making these arguments have their own favorite language and they’ve all been on HN dozens of times, but a custom assembly language is a weird thing to have done, almost no one outside the hardcore golang community thinks it’s sane, the problems is creates for build systems and FFI and just everything about actually running the stuff are completely unnecessary: there are other IRs, not all of them are LLVM IR if you’ve got some beef with LLVM IR, and given that go doesn’t seriously target FFI as more than a weird black sheep (cgo) there’s, ya know, assembly language. It’s a parting shot from the Plan9 diehards with the industrial clout to make it stick. The garbage collection story is getting better but it’s an acknowledged handicap in a MxN threading model context, it’s not a secret or controversial even among the maintainers. See the famous “Two Knobs” talk. Raw pointers, sum types, dependency management, build, generics that never get there, FFI: solved problem after solved problem killed by pocket veto, explained away, minimized, all with mega-bucks, quiet as a gopher corporate sponsorship fighting a Cold War against Sun and the JVM that doesn’t exist anymore marketed by appealing to the worst instincts of otherwise unimpeachable luminaries of computing. There is great software written in golang by engineers I aspire to as role models (TailScale and Brad respectively as maybe the best example). I had to get serious about learning golang and how to work around its ideologically-motivated own-goals because I got serious about WebRTC and Pion (another great piece of software). But it sucks. I dread working on that part of the stack. Go enums do suck, but that’s because we pay a very heavy price for golang being mainstream at all: we’ve thrown away ZooKeeper and engineer-millennia of garbage-collector work and countless other treasures, it sucks oxygen out of the room on more plausible C successors like D and Jai and Nim and Zig and V and (it pains me to admit but it’s true) Rust. Yes there is great software in golang, tons of it. Yes there are iconic legends who are passionate about it, yes it brought new stuff to the party and the mainstream. But the cost was too high.
- ptman 3y agoHow does this compare to enumer? https://github.com/dmarkham/enumer https://github.com/dmarkham/enumer
- binary132 3y agoYes. And?
- 0xjnml 3y agoGo does not have enum types and Go does not have [Pascal-style] subrange types. The correct title should read "Go named constants suck", but then I'm not sure what's wrong about them.