6 ms·
Golang proposal: container/: generic collection types
- troupo 2mo agoGo is rediscovering Guy Steele's Growing a Language from first principles, at a much slower pace: https://youtu.be/_ahvzDzKdB0?is=qZdfiT3792XyHxSJ https://youtu.be/_ahvzDzKdB0?is=qZdfiT3792XyHxSJ
- deleted 2mo ago[deleted]
- pstuart 2mo agoSounds like a win to me. I'd assume that many PL decisions come with with costs of either implementation or readability, and Go's conservative evolution takes that into account. Disclaimer: not a PL designer, just a codemonkey. It's not a perfect language, and the process has not been without its pain points, but work like this makes the language more powerful and I feel like I get my money's worth when I use it. Yes, I'm a Go fanboy but I'm not interested in language wars (e.g., yes Rust is more performant and correct but sometimes "good enough" is good enough).
- cyphar 2mo agoOn the other hand, design decisions made under one set of constraints can become problematic when you add new features that don't play as well with earlier design decisions. For a concrete example, the fact you cannot define custom methods for external types in Go (a pre-1.0 design decision) means that you cannot write proper compile-time generic code to deal with some generic wrapping type (dumb example -- getting a sum of the perimeters of a generic set of shapes in an externally-defined collection type) -- you are forced to work around it with runtime type-switching. There are all sorts of arguments you can make about simplicity but this is an objective shortcoming of Go that is directly caused by generics being added to Go long post 1.0. My take on this is that despite selfishly wanting more from Go for many years myself, adding more stuff to Go at this late stage is just slowly chipping away at Go's uniqueness with features that make a large number of people using them unhappy. (For example, while they make some APIs nicer, iterators turn a basic logic bug that is impossible with for loops -- forgetting to stop iterating when the loop has a "break" -- into a runtime panic. And they really suck to compose.)
- pstuart 2mo agoFair enough. Primeagen did a video recently renouncing his love of Go over the concerns you've raised. That said, I'm assuming much of this "wobbly" functionality will live in libraries and will not be common in day to day coding (much as I've seen with generics so far). It's all optional after all. I use Go because it's simple, capable, and been my prime language for over a decade and that skill enables me to be valuable enough for a decently paying job. If I were younger with more energy and time on my hands I'd likely be a rustacean but I think I can ride out my career on this. YMMV.
- cyphar 2mo agoI've maintained one of the major container runtimes (which is written in Go) for over a decade as well, I think I have a less rosy view of Go than you but I still think it's a nice language all things considered and still use it for some projects.
- pstuart 2mo agoMy goal is to be pragmatic about the issue (and everything else). When I started with it I saw it as the love-child of C and python. Then saw it as a successor of Java. I recognize that Rust will win this contest (although my understanding is that async still has sharp edges to round down). I'm old and tired and have lost the energy and focus for exploring new languages and believe that despite its shortcomings it will continue to have enough value to be useful. Good enough will do for me. I tip my hat to the all the other PL contenders and wish them all well (except Java -- PTSD from that destroyed any love I had for the language).
- tikhonj 2mo ago"Everything is a trade-off" assumes you're on the Pareto frontier. Go is... very much not on the Pareto frontier of programming language design.
- pstuart 2mo agoI find language wars tiresome at this point. There was no claim that it was a frontier language, or even that it was a great language. My point was that the Go authors do try to consider the impact of enhancements to the language, which I think is appreciated by many that use it.
- fragmede 2mo agoSomewhat. The trade off is it can be made more complex at the cost of its simplicity. You can argue that some of those tradeoffs don't in fact have to be made because it's not on the Pareto frontier, eg generics, but we'd have to have a specific discussion about specific language features instead of vague generic discission about the language.
- whateveracct 2mo ago> "Everything is a trade-off" assumes you're on the Pareto frontier. 100%. it pisses me off so much that i have to hear this idea thrown around constantly.
- silverwind 2mo agoIt's sad that such basic stuff took this long. If we're lucky we might even see a `Map` function in our lifetimes.
- wannabe44 2mo agoMap function leads to poor code in Go. Function literals are verbose and inlining is far less agressive. It simply isn't the way of the language. Even python shuns map and filter in favor of comprehensions. A for loop is more readable than the lambda soup.
- ninkendo 2mo agoIMO it depends on the language… to me, map/collect/etc are useful in languages that have the concept of immutable data, because you can initialize an array with a single call chain, and be sure that nothing after that can modify it. What I’ve seen in the “for loop” approach that I can’t stand, are things like (pseudo code) var a = [] for x in coll1 { a.push(foo(x)) } do_stuff_with(a) // … further down the function for y in coll2 { a.push(bar(y)) } do_other_stuff_with(a) Reading code like that, is the first call to do_stuff_with(a) a bug, because it’s not fully built from both coll1 and coll2 yet? Or is the second call to do_other_stuff_with(a) a bug because a now contains more stuff than the developer probably thought? Can I safely move both loops next to each other, or does that break something subtle? If I need to pass a to a new function, where can I safely do this? Before or after I add from coll2? (In my actual times seeing this, a is really a map of cached key/values or something, and it’s kinda ok that the contents were different each time it was used, but subtle bugs emerged…) IMO the sane way to do it is to just not incrementally mutate things like that, and stick with giving things a single place where they’re defined and initialized. Go doesn’t really help you here because there’s no such thing as immutable data. So just adding Map/collect or whatever doesn’t really buy you much.
- tialaramex 2mo agoOften the mutation might have performance benefits. Of course if you're Rust the stdlib and compiler might conspire to optimise an operation you wrote which reads as non-mutating into an actual mutation which was faster. This is another benefit of the "destructive move". If I consume X and spit out Y, the X is gone, so it's OK if secretly I just mutate X and tell you that's Y now.
- athorax 2mo agoOn one hand I'm glad to see this being added, but its becoming obvious building generics into the language as-is just isn't a good fit. Hopefully Go v2 can solve this at a more foundational level while still allowing interop or easy porting form current go code.
- bananamogul 2mo agoI thought the status of Go v2 was that the devs weren't saying it will never happen, but also were not working on it. There was some momentum that seemed to sputter out once generics were added. "when should we expect the Go 2 specification that breaks old Go 1 programs? The answer is never. Go 2, in the sense of breaking with the past and no longer compiling old programs, is never going to happen. Go 2 in the sense of being the major revision of Go 1 we started toward in 2017 has already happened."[1] Granted, this post was more about if there will someday be a Go that will break backward compatibility. But it sort of answers where Go 2 is as a side effect. [1] https://golang.google.cn/blog/compat https://golang.google.cn/blog/compat
- orf 2mo agoWhy is it becoming obvious?
- nasretdinov 2mo agoWhy isn't it a good fit? The design prioritises readability of code that uses generics vs writing generic code (which is in line with the overall language philosophy). It also does it in a way that doesn't impact compilation speed or add too much complexity, which is also in line with the language philosophy. If you don't like the fact that not all of standard library has been refactored to support the new language features -- I think it'll come over time. Once these features land into the standard library they can't be taken away, so the language authors take their time to make sure it's designed well. I don't see anything going obviously wrong here.
- TheDong 2mo agoI agree it's not a good fit. Go is a language built for people who don't wish to learn any math or CS theory, for people who don't wish to be "computer scientists" but rather "grug-brained programmers". The new datatypes will mean having to read things like "sz := sx.Union(sy)", and the union operation between sets is too math-like, and thus makes it less readable. "Advanced" data-types, like sets and heaps, only make code more readable to okay programmers, it makes code less readable to the average go programmer. To the average go programmer, a union operation is more readable as a for loop which does not have any math-y sounding name at all.
- deleted 2mo ago[deleted]
- nasretdinov 2mo agoWell, better late than never. Stuff like sets or a typed heap is long overdue. Maybe they'll even add iterator API for database/sql results this decade too (something like my pull request for sqlx https://github.com/jmoiron/sqlx/pull/990 https://github.com/jmoiron/sqlx/pull/990 but maybe more polished)
- nasretdinov 2mo agoAlso having stuff like a concurrency limiter (instead of doing weird var limiter chan struct{} and using it as `limiter <- struct{}{}` and `defer <-limiter`) as a library function in `sync` package would be great too.
- aatd86 2mo agoBut I guess the issue is that oftentimes, it is more of a distributed system coordination issue? What use case do you have in mind?
- arccy 2mo agothere's https://pkg.go.dev/golang.org/x/time/rate https://pkg.go.dev/golang.org/x/time/rate ...
- astonex 2mo agoThere is actually a way to do this with errgroup provided you can work with func() error signature https://pkg.go.dev/golang.org/x/sync/errgroup#Group.SetLimit https://pkg.go.dev/golang.org/x/sync/errgroup#Group.SetLimit
- inigyou 2mo agoError 403. Summarize?
- theowaway213456 2mo agoerrgroup has a SetLimit function to control the max number of concurrent go routines running at once.
- znpy 2mo agoLooking forward to see G2EE being released as a specification /s
- throw_m239339 2mo agoNothing wrong with J2EE back then if you were building a certain kind of entreprise application. EJBeans actually took care about a lot of business complexity for a n-tier application, it's just that the whole XML crap was absolutely egregious. Go can barely parse an XML document natively so don't worry about G2EE I'd say... I'm more worried about what have become of professional Javascript serverside these days, it's just nuts how people have managed to make it as complex as J2EE... Nextjs, Typescript,JSX, React, compilers, transpilers, ... and none of that stuff solves enterprise business logic...
- znpy 2mo agoAbsolutely, i was just being ironic :)
- pjmlp 2mo agoWhat do you think Kubernetes is? Go EE is the plethora of CNCF projects.
- znpy 2mo ago> What do you think Kubernetes is? Essentially an abstraction layer above the infrastructure (physical or virtual). Considering it was released by google AFTER the launch of google cloud platform, i honestly see it as a way to make apps more easily portable off AWS.
- pjmlp 2mo agoGoogle Cloud platform is based on the internal proprietary version of Kubernetes, Borg.
- jiehong 2mo agoWell, finally! I wish they wouldn’t mix mutation methods in there, but ok.
- akiarie 2mo agoHonestly the more I see this the less I like Golang. Generics was the worst thing ever added to the language. We're making it easier for library builders and harder for ordinary code to be written.
- woodruffw 2mo agoIs there a categorical division between “library builders” and “ordinary code”? That’s not one I’ve heard before. (I’m aware of the difference between application and library code, but every large codebase I’ve ever worked in is a mixture of both.)
- pstuart 2mo agoI'd say library builders are focused on specific capabilities and doing so as cleanly and efficiently as they can. App builders just want to build stuff and make it work and move on to the next app. Nothing wrong with that but a different mindset and approach.
- pphysch 2mo agoThis proposal is literally about making it easier for ordinary code to be written without defining new generic types or iterators.
- troupo 2mo agoHere's a quick example of ordinary code that is much easier to write with generics: https://news.ycombinator.com/item?id=49128954 https://news.ycombinator.com/item?id=49128954 Working on any collection is easier with generics. Working with anything that accesses data in uniform way (APIs, SQL etc.) is easier with generics.
- jerf 2mo agoDo you use Go? Because it sounds like no. In the last four years I've encountered I think two uses of generics in the wild in a 3rd party library. Both quite sensible. Anyone moaning about how it's ruined Go is either not using Go, or simply impossible to please. If you hate Go... and hey, you do you, I've got my own list of languages I don't like... find a better complaint because this one is simply nonsensical. "It doesn't let me map/filter/reduce" or "it doesn't fix lock problems" or other similar complaints have some grounding in reality, but this one is just absurd. Generics aren't used enough to be "the worst thing ever". Fears about how Go would instantly turn into a language full of generics that take generic arguments that take generic arguments have proved to be wrong.
- shevy-java 2mo agoGolang's biggest problem is a certain company.
- quchen 2mo agoI'd say it's quite the opposite, Google is the only thing that made Go become somewhat popular.
- improgrammer007 2mo agoFirst they said they won't add generics. They violently defended that decision. Developers bent over backwards to make it work without generics. Some even wrote long blog posts defending Rob Pike's decision. Some wrote posts arguing against it. Now the Golang team adds them. Why waste so much developer time? It's not a few months. It's several years. This industry is seriously a clown show tbh.
- amazingamazing 2mo agoWhat’s wrong with meeting demand?
- improgrammer007 2mo agoNothing is wrong. What was wrong before when they vehemently argued against adding it? Is that design principle/core value lost now?
- ninkendo 2mo agoReminds me of when Apple finally moved the iPhone to USB-C… they defended lightning for the longest time, but then when when they finally did the switch, all I could think was “the last N years [0] of lightning accessories I’ve bought are now ewaste”… once it became clear USB-C was going to be the future, every year they weren’t using it was another year of future ewaste building up. Every year go didn’t have generics was another year of workarounds and tech debt building up that would have otherwise been able to be written the right way from the start. Unlike ewaste though, it’s probably impossible to quantify. [0] I’d probably peg N as the years between when they gave MacBooks USB-C ports for charging, up until the iPhone got them. It’s clear Apple knew they were gonna need to move to it eventually… every year in that period represents a year of lightning cables people bought that could have been still-useful USB-C cables today.
- kokada 2mo agoTechnical debt, sure. But you could argue the same for any new feature added to a programming language, without having X you will need to workaround with Y, generating technical debt. To be clear, I was one of those people that only started to use Go after generics. But for most of my projects, generics is less than 1% of the code base, so it is not like lack of generics was a huge issue. I think it is more of a problem for libraries in general.
- DarkNova6 2mo agoStep by step, Go is now learning the hard lessons every other language has learned over the last 20 years. The fact that despite their best efforts, their propositions look like everone else is a surprisingly refreshing affirmation of status quo.
- somekyle2 2mo agoI respect "we're going to try not to add features until we have to and have a plan that we like" as an approach to a practical language, vs "we're going to plan to support everything normal modern languages have". It isn't the best approach to language design in theory, but they did try to build a language that isn't impossible to change, and to be fair the mix of language features they chose didn't have any good more successful examples to borrow from, so waiting for enough practical experience to make the relevant trade-offs on practical grounds isn't the bare naivety that some people seem to take it as.
- vlovich123 2mo agoThe problem is that when you don’t have a cohesive picture of how things fit from the outside, it becomes really hard to evolve the language in a way that makes sense and doesn’t break existing code. Data storage and languages share this unique property that the past impacts your decisions and what makes is possible in the future in a way pure logic doesn’t struggle with.
- Sleaker 2mo agoAnd this is -exactly- one of the reasons they didn't accept or continue with a sane proposal for more ergonomic error handling. I like go, but this was the one thing that I kept feeling like I was wasting so much time dealing with.
- win311fwg 2mo agoPresumably you are referring to https://github.com/golang/go/discussions/71460 https://github.com/golang/go/discussions/71460? While the proposed slightly reduced the token count, saving the average typist approximately 1 second of time if they don't have an autocomplete editor that types it for them, it doesn't change anything about the mental model where the real time is actually spent, so is it really sane? Worse, it is dependent on the error type, but errors are not always of the error type. Not even Go's own standard library consistently returns errors using the error type, never mind all the other crazy things you find in the wild. That doesn't sound sane at all. It is true that Go not having any real kind of superpositions or side channels makes stealing popular ideas from other languages impossible (it already has both well-known error handling methods that do not depend on those properties). But a sane proposal would be designed with that in mind.
- valcron1000 2mo ago22 years late, but better late than never.
- roundwego 2mo agoA bit too late frankly. The snobbish arrogance didn’t help.
- kamma4434 2mo agoWelcome to Java, where Collections are the bread and butter of every programmer since 1998. While you are at it, I humbly suggest to add composable streams too, that we had in 2014, and that make working with collections way more pleasant. (Jokes aside, in Java it is very nice that you can start with a generic ArrayList and turn it into a linked list with one single keyword change and no code needs changing, or that you can turn any collection into a synchtonized or readonly doppelganger with one line of code. Collections are nice and I miss them in Golang)
- pjmlp 2mo agoActually welcome to Smalltalk, 1980's, because that is where collections, and iteration with blocks, comes from as inspiration to Java, and all the folks that think LINQ was a .NET invention.
- shikck200 2mo agoJava? No thanks. I have some horrible memories from the ugliness, verbosity of Java. The cherry on the cake is the huge hog of an runtime called the JVM. Also java semi-forces you to have some bulky IDE. Last i looked there was no core java lsp server bundled in the tooling. Java is the enterprise language that make programming suck.
- Shish2k 2mo agoNone of that is anything to do with collections
- alfiedotwtf 2mo agoNo reference to Canadian Aboriginal characters in the comments :(
- pif 2mo agoPeople still calling themselves developers and choosing a language that was created for poor programmers...
- win311fwg 2mo agoThe problem good developers have is that they develop software people want to use, and software that people want to use eventually requires more help, and once you need help then it is inevitable that you will need to bring poor programmers into the mix. A good programmer may respect the beauty of Haskell, but it isn't a practical option for them. Ironically, only poor developers have the luxury of being able to choose something like Haskell as they never have to worry about building something anyone else wants to use.
- foldr 2mo agoIt’s the same principle as accessibility. We are all poor programmers sometimes, just as we are all impaired in various ways at times even if we don’t have a disability.
- dgunay 2mo agoIt's cool that they're doing this but with iterators and soon in 1.27 generic method parameters, you can already DIY most of this with little effort. I've got iterators at work for nearly everything I could want, small libraries for extra mapping, filtering etc operations, and with agents going back and actually refactoring old code to use them is easier than ever.
- ncruces 2mo agoWell adding the language features is a prerequisite to making these libraries possible.
- vander_elst 2mo agoI find it so sad that people wasted millions of hours and lines of code rewriting over and over basic constructs that should have been on the language in the first place. How many years before we finally get sum types?
- epolanski 2mo agoIt's not like your idea is bad, is that each abstraction eats in one of the fundamental strengths of Go (simplicity and compilation times).
- gadflyinyoureye 2mo agoGo was never simple in action. The fact that you'd panic a nil map but not a nil slice is a foot gun. It's a pretty big foot gun. It's just one of the many foot guns.
- everybodyknows 2mo ago> Since the addition of generics in Go 1.18 and iterators in Go 1.23, it has become possible for library-defined types to achieve comparable ergonomics to built-in types ... For those who've been following Golang more diligently than myself: Is there a way now to define a slice-based type that enforces strict typing of its index, and yet preserves the compactness of the standard syntax "s[i]"?
- bheadmaster 2mo agoWhat do you mean by "strict typing of its index"?
- dwattttt 2mo agoI expect it's referring to the newtype pattern; you don't want to accidentally add inches to cm, so if you have to handle both of them a lot, you make a single field struct Inches and one for Cm. For containers, you can do this to make it a type error to index the container with anything other than the newtype you made. In some languages you can replace/implement the indexing operation a[i] with your new type, so the code looks the same as usual, but gets the benefit of preventing the wrong 'integer' from being used.
- kubanczyk 2mo ago> Is there a way now to define a slice-based type that enforces strict typing of its index Nope, no way to do that. I wonder about ergonomics. I can imagine "academic" usage, but I shudder at the perspective of the impact on a typical CRUD app.
- throwgolang 2mo agoAs if generics weren't bad enough, they want more?