17 ms·
Why Generics?
- aczerepinski 7y agoMixed feelings about this. One of my favorite things about Go is that it's a small and relatively simple language. It's a "fast enough" language without the steep learning curve of Rust. Too many features that make sense individually could change the calculus to "might as well use Rust".
- aldanor 7y agoI'm not so sure about the "steep learning curve of Rust" stereotype anymore. If you are comfortable with low-level programming languages in general, in a few days you can get yourself started fairly quickly with Rust to the point where you will still battle with compiler re: borrowing and related things, but will be able to write functional code. Coming from pure Python/JS will be tough, but it will be the same with any other low-level language.
- aczerepinski 7y agoMy work is a Ruby/JS shop, and we have some Go in production as well. We definitely need a little hand holding to ramp anybody new up on the Go codebases. In many cases our devs haven't used types, pointers or any equivalent of goroutines & channels. I've written just barely enough Rust to say there are even more concepts that would be new to my team. Even with Go being comparitvely simpler, I could go either way on whether it was the right choice to add it to the stack.
- LandR 7y ago> In many cases our devs haven't used types, pointers or any equivalent of goroutines & channels. How do you manage to get a job as a developer without having ever learned this stuff? Are these people that are just self taught straight to javascript / ruby? I mean, are CS course nowadays so bad that students come out of them without understanding things like type-theory, pointers etc
- aczerepinski 7y agoTo be honest, this response feels a bit aggressive and dismissive to me. Many of my coworkers (myself included) entered the profession through bootcamps. Others came up during the PHP/Wordpress to Ruby/Rails era of web development, and never had a reason to learn languages like C++ or Java. I don't think there's anything to make fun of, or apologize for in this scenario.
- chessturk 7y agoThe shop I'm part of is staffed by bootcampers or fully self-taught people. Not a degree in sight. They have to be passionate about code/computer/the web/technology/math/some associated subject to thrive, but when they are, it seems to work out. I'm lead to believe this is the relative norm for web development. Bootcamps do not teach things like pointers, type-theory, or big-O notation. I'm not sure what they do teach, I'm self-taught and via MIT Open Courseware + other net resources, have learned a lot about those, but I have no idea how that compares to either bootcamps or modern CS courses. Not all of my colleagues know about pointers or type-theory, but the senior ones do. I don't know if my experience is unusual though. edit: nicer formatting.
- jsgo 7y agoGenerics with Reflection was the first gut check I experienced while working after completing college and getting an ASP.NET job. Like 2-3 weeks into said job. Had to do an application that dealt with 4-5 forms (can't remember). Like 300 fields on the bigger ones, smaller ones 50ish. I started out on one that was mid-200. I'm coding the way I was taught in school: object set object properties based on txtWhatever.Text. Like 240ish times. I can't remember how many lines of code were in this code behind, but it was substantial. I turn it in, it works. Go me, let me go on to the next one. The senior guy on the team does one of the smaller forms. But he uses generics and reflection to basically iterate over all of the fields on the form and sets them to the ephemeral properties on this generic object in like 8-9 lines of code. Then there was the rendering code that was vaguely similar. Added bonus: 99% of his code behind could be copy and pasted over to the newer forms and handle all of the work related to getting/setting form values. After the code proved to work for a few weeks, replaced the massive code behind with call to his code (passing in the form object and the generic to be set and used later) with the same result and one area to manage code and it isn't an insanely large code behind file (got better with not one filing everything in time too). Not saying generics and/or reflection are a silver bullet (I don't feel they are. Rarely so do they end up being the thing I go for), but it was definitely eye opening that straying from "see spot run" code could be advantageous. And that I wasn't "good to go" already.
- baby 7y agoI have two comments to make about this proposaL: 1. The type should indicate a generic, not a new syntax. This is better because it is easier to parse for the human eye. For example: func Reverse(first _T, second _T) 2. Since all of what generics are is a compile-time code generator, I suggest that Golang forces developers to explicitly list what types are using the generic: generics(Add) = {int, string, car, food} func Add(first _T, second _T) This list can be added to, after importing the package: Import “thing” generics(thing.Add) += {stuff} This makes code very explicit about its generic functions. It also allow readers to understand exactly where the function is used.
- zeveb 7y agoNot certain I like that this is now valid Go: func Foo (type T) (t T) (t T, err error) { … } Seems like an awful lot of parentheses in a single line! It's a bit tricky to read, because 'generic function' here means something subtly different from what 'generic function' means in CLOS …
- mseepgood 7y agoIt's not more parentheses than in a method definition: func (a A) Foo(x int) (n int, err error) { … } Also your line isn't formatted properly. It should be: func Foo(type T)(t T) (t T, err error) { … }
- phlakaton 7y agoI do not think generics should be added to Go. It does minimalism and it does it tolerably well. Yet I enjoy using generics in other programming languages. If I had my druthers I'd be in Haskell-land in more than my spare time. Hence, my modest proposal: Add generics, but make it a brand-new programming language with a totally different name. Sadly, the name Blub is already taken. I propose we call it Glop. Or perhaps: Gong.
- sp527 7y agoThis process took way too long. I've already moved back to Python3 and am super happy with it. The truth is most software doesn't really need the performance benefit Golang offers and you can code up something in Python in at least half to a third of the time it would take in Golang. Aside from agility, there's one other benefit that imo matters a lot: reduced LoC. If there's one thing I've learned in my career, it's that you can never really have too few lines of code, provided it achieves the same result as a hypothetical more verbose alternative. I will admit though that I miss Go's CSP implementation and error-handling convention. Maybe I'll come back to it in the future after they add generics and fix the dependency system.
- mcguire 7y agoCan I sell you some Pony: https://www.ponylang.io/ https://www.ponylang.io/
- merlincorey 7y agoAs a functional leaning programmer, I think it's striking that the resulting draft is essentially a curried function whose first parameter is the type! func Reverse (type Element) (s []Element) { first := 0 last := len(s) - 1 for first < last { s[first], s[last] = s[last], s[first] first++ last-- } } This is later called like: Reverse(int)(s) Which if this were a curried function, would also be callable like: Reverse(int, s) Now I wonder if facilities for currying functions might be a higher level addition that could result in the same thing (so long sa we can pass bare types, which is part of this change as well).
- mcguire 7y agoI hate to tell you, but you're on your way to dependent types.
- SomaticPirate 7y agoOne of the things I like most about this is that Ian includes the simple mistake in the first function. It’s a bit humbling and acknowledges the fact that even the best of us often make trivial mistakes. It also helps make the point that even the simplest code needs a basic test and adds another argument in favor of generics on the premise of duplicating tests.
- jayd16 7y agoIf I'm understanding correctly, contracts are a way to implement compile time duck typing? If that's the case I think its a pretty neat twist on generics.
- mcguire 7y ago"This article is about what it would mean to add generics to Go, and why I think we should do it. I'll also touch on an update to a possible design for adding generics to Go...." This is a situation where who is making the proposal is more important than the proposal. "By Ian Lance Taylor" Oh. Ok. I guess it's worth reading then...
- wwarner 7y agoI feel pretty good reading this. I like that you can write listMyType := List(MyType). I'm still a bit dubious about contracts; they're so similar to interfaces. If there was a way to derive or relate a contract to an interface that would help me.
- jordiburgos 7y agoThis looks as an strategy to keep people (and HN) talking about Go.
- haolez 7y agoPersonally, I prefer the current interfaces-based solution to generics. It's a little verbose, but keeps the language simple. However, I think that the people we should be listening most are the ones developing huge projects in Go, like Kubernetes. Would having generics with this new contracts thing make it easier to develop and maintain e.g. Kubernetes? I'm truly curious.
- dotaheor 7y agoYes, I think. Now, the kubernetes project uses too many code generators, which makes it is to extend.
- saturn_vk 7y agoI take it you've never actually read the K8s source code.
- YawningAngel 7y agoKubernetes is a transpiled Java project, so yeah, Java-like features would definitely make it easier :P I think idiomatic golang works pretty well without generics in most cases, the big problem for me is that functional programming is essentially impossible without them.
- yureka 7y agoCan you provide some resources on what makes you think Kubernetes is a transpiled Java project? That's definitely not the case from what I know/understand...
- throwawayoo 7y agoWhat are Generics?
- mlevental 7y agowhy are people obsessed with simplicity? there's a quotation my Einstein that I like to keep in mind: "make things as simple as they can be but no simpler". the implication being that if you make things too simple then you actually break things. lack of generics makes for software that's actually more complex than it needs to be. Take for example Swift: lots of complex features (protocols, all manner of functional transformations, generics, enums, structs, iterators, objects with many method qualifiers, etc) but really nice and efficient to program in.
- astrobe_ 7y ago> why are people obsessed with simplicity? > "make things as simple as they can be but no simpler". Those people are obsessed, precisely, with the "can be".
- dimgl 7y agoI have yet to find one practical application for generics in the apps I've built in Go.
- mcguire 7y agoIf you've never used a screwdriver, all you can say about screws is that they make crappy nails.
- rad_gruchalski 7y agoEvery project I’ve written so far in golang could benefit from generics.
- freetobesmart 7y agobut what is the benefit? How does your code change. Generics are a tail abstraction. Its the last abstraction that you are able to make to your code to reduce boilerplate. This usually means that is the least useful and in generics specific case the boiler place it reduces is minimal. Its lack of impact is why I dont really care about the subject. Adding or removing generics to a project matters little. So why bother complaining. The class creation and encapsulation choices are much more impactful to future code edits.
- moomin 7y agoGo 3: Why HKT? Go 4: Why homoiconicity? Go 5: Why uniqueness and borrowing?
- sjapkee 7y agoSo, ten years and Go will be production ready.
- gclaugus 7y agoI am ok with this progression.
- adamnemecek 7y agoIt's all bolted on.
- olooney 7y agoWhat is HKT?
- deleted 7y ago[deleted]
- eslaught 7y agohttps://www.google.com/search?q=higher+kinded+types https://www.google.com/search?q=higher+kinded+types
- deleted 7y ago[deleted]
- sli 7y agoGenerics are to types what HKT are to type signatures. In functions, they usually map to arity. That is, an arity mismatch is are a higher-kinded type mismatch. An easy (if not totally accurate) way to view them is like doubly-generic types. If you have some type A, it has the kind * . If you have some function from A -> B, it has the kind * -> * .
- sansnomme 7y agoI think another area of Go that could use improvements is a more portable standard library optimised for embedded and OS dev. A lot of people want to use Go as a "systems language" and do drivers etc. in it. But the standard library don't have good support for freestanding, or at least it's not a priority. C and Rust and other languages designed for usage in a non-hosted environment have very clear delineated areas of runtime that requires assembly, manual interfaces for IO/memory allocation etc. Go's runtime by default assumes the presence of an operating system.
- jerf 7y ago"Go's runtime by default assumes the presence of an operating system." It also assumes the existence of several megabytes of runtime and enough RAM to feasibly use GC, which if nothing else is probably a real mess when it comes to drivers. What you probably need, rather than being a second-class citizen of the main Go language indefinitely, is a separate dialect that is close to Go, but can go its own way if it makes sense, like: https://tinygo.org/ https://tinygo.org/
- sansnomme 7y agoThere is nothing wrong with GC. There exist plenty of network stacks in production that are written entirely in Go (See Docker/Kubernetes et alia). There are also operating systems that have GCs, such as Oberon or the few C# OSes written by MSFT and others. As long as care is taken to isolate hard real-time requirements when needed, a GC is perfectly fine. There is a real advantage to Rust's style of explicitly marking no_std. After all, what's the point of using stuff like tinygo (other than for performance/resource reasons) if it cannot run most of the existing Go libraries?
- parhamn 7y agoThat time of week to rehash all the Go Generics comments! https://hn.algolia.com/?query=generics&sort=byPopularity&prefix&page=0&dateRange=all&type=story https://hn.algolia.com/?query=generics&sort=byPopularity&pre...
- dotaheor 7y agosort by date: https://hn.algolia.com/?query=generics&sort=byDate&prefix&page=0&dateRange=all&type=story https://hn.algolia.com/?query=generics&sort=byDate&prefix&pa...
- Filligree 7y agoWhy generics, indeed? There must be an answer to this, but I've never seen a good response to why they aren't implementing parametric types and (single-parameter) typeclasses instead. Simplicity? Yes, but generics are hardly any simpler.
- silasdavis 7y agoPerhaps I'm misunderstanding, but I would have thought go already implements typeclasses and this proposals extension to the interface semantics is a parametric typeclass? Would you mind elaborating?
- mda 7y agoFor me, generics make api designer's life harder, but api user's life easier. A good enough reason for me.
- elpakal 7y agoChiming in here as a Swift dev - I find its generics system incredibly helpful and end up writing something that uses generics about once a month. To those Go programmers who think they will never use them - it’s worth a little learning, and once you do you will find more ways to use them to make your code more applicable.
- Vendan 7y agoChiming in as a fervent Go dev that's also a huge fan of generics: Generics are awesome, but always seem to add a ton of complexity. Everyone starts with just "oh, `func Reverse(slice []T)` is so obvious" kind of thing, but that's like saying `fmt.Println("Hello World")` is simple. It's simple cause you are doing a simple thing. That said, I do want generics to come to Go, just... with an emphasis on what Go is, not just "here, let's replicate X's generics in Go". I am interested in the contracts implementation.
- Nevermindmine 7y ago> Generics are awesome, but always seem to add a ton of complexity The team I work in use generics all the time and I'm not sure what complexity you are referring to. Care to elaborate? Is it some edge cases or are you talking about from a compiler perspective or something else? To me, not having generics is like saying let's skip handling bools and just store them in strings as "true" or "false". It's such a weird thing from my point of view.
- nevir 7y agoI think TypeScript is a good example of one extreme. You've got conditional types, literal types, type mapping, and a bunch of other very advanced parameterized types. (I also think it makes sense for TypeScript given JavaScript idioms; it mainly falls over when the caller has to interpret some very complicated error messages, however)
- Vendan 7y agoCompiler perspective (fast compiles are a core part of Go, IMO), various tradeoffs(fast compile? fast runtime? binary size? Pick 1 or 2), and seeing code bases that get out of control with generics and such. Note that, for all of that, I'm still in favor of adding generics in Go, as I do see the value they can add. I'm just pointing out that "bashing" on Go devs on not knowing what generics are or how they can be useful is both non-productive and probably generally wrong. Plenty of us are saying "Man, if I had generics, this would have been less code/cleaner/more reusable!", just the other various tradeoffs outweigh the actual cost of using a different language. Go's ability to drop a very junior dev (or just one that has never use Go) into a codebase and have them be almost immediately productive is incredible.
- fabiensanglard 7y agoI hope this doesn't happen. I love golang because it is simple and easy to read. Both will go away when generic programmer start to write unreadable meta-programming class which "you don't need to understand, just use them". I admire golang devs for being opinionated and stand up for the core lines of their language so far. I see generic as renouncing these principles.
- theli0nheart 7y agoI don't think it's as clear-cut as you make it seem. Generics greatly reduce the amount of code we need to read in exchange an slight increase in abstraction. In my opinion, the tradeoff is worth it, especially given that Go already has abstractions that are more difficult to grok than generics, which, all things considered, aren't that hard to understand.
- owaislone 7y agoMay be you could share feedback with us and the designers about which parts you think will be hard to understand? This is a valid concern but only way to address this is to specify and share as feedback to the proposal.
- jasonwatkinspdx 7y agoThis design does not permit metaprogramming.
- tylerflick 7y agoThis. If I really need generics I'll use a different language.
- wrs 7y agoThe examples I’d like to see worked out fully, which he mentions in passing, are encapsulation of concurrency patterns (parallelization, work queues, cancelling, etc.). It’s not that big a deal to write Max as a function or even inline, whereas there are serious practical pitfalls and common mistakes when doing real work with channels. It would be a lot more effective to fix these by writing library code rather than writing Gophercon presentations.
- mitchellh 7y agoIt might be fun to share my viewpoint from an angle that's probably fairly unique. I've started a number of large, highly deployed Go projects: Terraform, Vault, Packer, Consul, Nomad, and numerous libraries and other things. I started a company that employs hundreds of full time Go developers. Go has been one of our primary languages since Go 1.0 (and I used it prior to that). Let me start by saying that there are _definitely_ cases where generics are the right answer. Usually when I talk about generics people tend to assume I disagree with the whole concept of generics but I certainly do not. Generics are useful and solve real problems. Adding this paragraph after I already wrote the rest: this whole comment ended up sounding super negative. I'm voicing concerns! But, I think that the design proposal is exciting and I am interested to see where it goes. There are definitely places generics would be helpful to us, so please don't take my negativity too strongly. ## Technical Impact Having written these numerous large, complex systems, I believe there are less than 10 instances where generics would've been super helpful. There are hundreds of more times where it would've been kind of nice but probably didn't justify the complexity of implementation or understanding. This latter part is what worries me. I've worked in environments that use a language with generics as a primary language. It's very easy to have an N=2 or N=3 case and jump to generics as the right way to abstract that duplication. In reality, the right answer here is probably to just copy and paste the code because the knowledge complexity of using generics (for both producer and consumer) doesn't justify it, in my opinion. As a technical leader, I'm not sure how to wrestle with this. Its easy today because generics just don't exist so you have to find a way around it. But for a 150+-sized org of Go developers, how do we have guidelines around when to use generics? I don't know yet. I guess that bleeds into human impact so... ## Human Impact! Something that is AMAZING about Go today is that you can hire a junior developer with no experience with Go nor any job history, have them read a few resources (Tour of Go, Go Spec, Effective Go), and have them committing meaningful changes to a Go project within a week. I don't say this as a hypothetical, this has happened numerous times in practice at our company. We don't force or push any new hires to do this, but Go is so approachable that it just happens. I love it! It's so cool to see the satisfaction of a new engineer making a change so quickly. I've been told its been really helpful for self-confidence and feeling like a valuable member of a team quickly. The Go contract design document is about 1/3rd the word count of the entire Go language spec. It isn't a simple document to understand. I had to re-read a few sections to understand what was going on, and I've used languages with generics in a job-setting and have also been a "professional" Go dev for 9 years. So what worries me about this is technical merits aside, what impact does this have on learning the language and making an impact on existing codebases quickly? I really like what Ian said about attempting to put the burden of complexity on the _author_ using generics, and not the _consumer_ calling that function. I think that's an important design goal. I'm interested to see how that works out but I'm a bit pessimistic about it. --- I have other viewpoints on generics but those are the two primary ones that stand out to me when I think about this proposal going forward.
- twodave 7y agoGenerics and interfaces go hand in hand IMO, especially in an application with heavy emphasis on data persistence. This way you can compose a class of some interfaces, pass it to a persistence layer (using a generic constraint of something common to all inputs of that layer), and then the persistence layer can check for all the interface types it cares about saving and pass those pieces off to whatever lower-level piece of code handles that one thing. Generics enable you to avoid having 10 slightly different implementations of the same thing (even if dependencies are shared, you're still going to have 10 copies of plumbing without generics). Being wise about when and when NOT to use generics is to me the most important factor. In our shop we tend to not introduce a new generic class/method until something gets painful (unless it's plainly obvious from the beginning). Because of this we usually begin to notice and reason about patterns in our code that seem common enough to warrant refactoring and whether the complexity of a generic implementation would be worth lowering the maintenance burden of copy/pasting said pattern all over the place. It's a case by case decision. Having generics available at least allows us to make that decision for ourselves.
- Pxtl 7y agoGo has generics. What it actually lacks is user-defined generics. Which shows the absurdity of the situation. The fact that it has generics demonstrates that generics are a useful and important feature. And yet they think their provided generics cover every possible use-case of generics that you will reasonably need in to use in Go.
- Vendan 7y agoAnd yet, the core devs have never said they don't want generics, only they didn't want a poor implementation. Also, there's a bit of hilarity about commenting this on a blog.golang.org where the first sentence is "This article is about what it would mean to add generics to Go, and why I think we should do it." being posted by a core Go dev....
- iainmerrick 7y agoMaybe this is unfair, but it’d be great if the Go devs could just say “generics will work similarly to [C# / Java / Swift / D / whatever], except that we’ll address [problems] with [adjustments]”. Rather than going through this whole rigmarole of resisting adding generics too early because all existing implementations are bad, then slowly reinventing the wheel from scratch, then finally ending up with something pretty similar to one of those other languages anyway. It’s OK not to make something completely new and different. It’d be useful to explicitly say which language(s) you’re borrowing from because you can then more clearly call out the differences and explain the reasons for them.
- grumdan 7y ago> because all existing implementations are bad I'm also not sure why in OOP-land, generics are this crazy experimental weird feature, when in functional languages, people figured out how to implement parametric polymorphism (the original term for generics) in quite reasonable ways. I get that subtyping adds some complexity, but overall I don't understand why such a basic way to build abstractions is so controversial in (some) OOP languages. If anyone has some context on why this is more difficult to have in Java-like languages, I'd be curious to hear it.
- RivieraKid 7y ago> I'm also not sure why in OOP-land, generics are this crazy experimental weird feature It's not, it's an essential, basic feature.
- evmar 7y ago
- 013a 7y agoThe proposed syntax feels like a caricature to me. That something like this could be easily possible: func (c Connection) Read(type T Writeable)(into *T) (int, error) { This is quite securely inside shark-jumping territory. Also; I haven't seen Rob Pike's name really anywhere in these blog posts or discussions, or on any recent Go blog entry. Is he still involved with the Go project day-to-day? I always got the impression that he was one of the bigger anti-generics voices on the team internally.
- monkeyfacebag 7y agoAs far as I can tell, the latest proposal draft forbids type parameterized methods. One must admit the type parameter to the receiver or define a type parameterized function. I am making no claims about your broader point, only clarifying that your example is not permitted by the proposal draft. See https://go.googlesource.com/proposal/+/4a54a00950b56dd0096482d0edae46969d7432a6/design/go2draft-contracts.md#methods-may-not-take-additional-type-arguments https://go.googlesource.com/proposal/+/4a54a00950b56dd009648...
- clamprecht 7y agoSuch a succinct article. I wish journalists could explain things this well.
- jknoepfler 7y agoThe decision to overload parentheses to express generic type is the only part of this spec I find nauseating. It doesn't scan well, and doesn't have a precedent in any major generic implementation I'm aware of. <, [, @-annotation... I don't care. Just don't mush it into the function declaration with the same syntax that encloses parameter.
- ohnoesjmr 7y agoSo much this.
- weberc2 7y agoAgreed, specifically it creates ambiguities in parsing (for computers but worse: for humans). Given Foo(x), you can’t tell if it’s a function call or a generic type without knowing what x refers to. You need context from afar to disambiguate.
- enneff 7y agoYou can tell if it’s a function call or a generic type based on where it is used; the local context. Function calls are either statements or expressions. Types appear in declarations.
- shhsshs 7y agoa := Bar(baz)(buzz) Is Bar a `func(some) func(thing) other` or is it a `func(type T)(some) other`? You need to know what “baz” is to be able to tell.