45 ms·
The Next Step for Generics
- ainar-g 6y agoLink to the current draft: https://go.googlesource.com/proposal/+/refs/heads/master/design/go2draft-type-parameters.md https://go.googlesource.com/proposal/+/refs/heads/master/des...
- saghm 6y agoI'm usually a bit of a skeptic when it comes to Go, but this proposal surprised me; for the most part, or seems like this is exactly what I would want if I were a Go programmer. Being able to define both unbounded generic parameters and parameters bounded by interfaces is key, and while from skimming I'm not sure if it allows giving multiple interfaces as a bound, in practice this shouldn't be a huge issue due to how Go's interfaces are implicitly implemented (which would allow you to define a new interface that's the union of all the other interfaces you want to require, and all the types that implement all of them will automatically implement the new one). Interestingly, the proposal also defines what is essentially a union type interface, which I think is something that Go definitely could use. Although there are a couple of minor warts (e.g. not being able to have generic methods) and the syntax is not what I'd personally pick, overall I'm pretty impressed.
- djur 6y agoAs someone who doesn't enjoy Go but is increasingly having to deal with it at work, I'm very happy with it.
- coder543 6y agoThis is the new code branch: https://go.googlesource.com/go/+/refs/heads/dev.go2go https://go.googlesource.com/go/+/refs/heads/dev.go2go I can't find the actual code review for this. It seems to be hidden/private still? This was the previous code review: https://go-review.googlesource.com/c/go/+/187317 https://go-review.googlesource.com/c/go/+/187317 The comment at the end is where I got the link to the new branch, but as an outsider, I don't have any good way to ask where the new code review is, so I'm leaving this comment here in hopes that a googler will see it and point me in the right direction. Based on a link that's on the new branch's page, it might be CL 771577, but it says I don't have permission to view it, so I'm not sure.
- ianlancetaylor 6y agoThere isn't a code review for the changes on the dev.go2go branch (though you could construct one using git diff). The dev.go2go branch will not be merged into the main Go development tree. The branch exists mainly to support the translation tool, which is for experimenting with. Any work that flows into the main Go development will go through the code review process as usual.
- Someone 6y ago“A type parameter with the comparable constraint accepts as a type argument any comparable type. It permits the use of == and != with values of that type parameter” I think that’s an unfortunate choice. Quite a few other languages use the term equatable for that, and have comparable for types that have =, ≤ and similar defined. Using comparable here closes the door for adding that later. I also find it unfortunate that they chose type SignedInteger interface { type int, int8, int16, int32, int64 } as that means other libraries cannot extend the set of types satisfying the constraint. One couldn’t, for example, have one’s biginteger class reuse a generic gcd or lcm function.
- coder543 6y agoLanguages have been known to use “Ordered”, “Orderable”, or “Ord” for what you’re calling “comparable”. Rust and Haskell are both languages that fit this criteria. The design draft refers to “constraints.Ordered”, so they’re definitely thinking about having both “comparable” and “constraints.Ordered”. Although, for consistency with “comparable”, I think it should be called “constraints.Orderable”.
- Someone 6y agoThat’s true, but both rust (https://doc.rust-lang.org/beta/std/cmp/trait.Eq.html https://doc.rust-lang.org/beta/std/cmp/trait.Eq.html) and Haskell (https://hackage.haskell.org/package/base-4.12.0.0/docs/Data-Eq.html#t:Eq https://hackage.haskell.org/package/base-4.12.0.0/docs/Data-...) use eq or similar for what this proposal calls comparable, as do C# (IEquatable), java (through Object.equals), and Swift (Equatable)
- coder543 6y agoSure, but as someone else already pointed out, “comparable” is an established Go term that refers to “==“ and “!=“ only, and “ordered” refers to the other comparison operators. My point was that “comparable” is not universally used in place of the “Ordered” term that the Go team is using, as you were seemingly implying. Ordered is a perfectly fine term for it. You said: > Using comparable here closes the door for adding that later. But the door is not closed in any way. It’s just called “constraints.Ordered”, which is perfectly reasonable.
- rb808 6y agoI like generics for collections but that is about it. I've seen "gifted" programmers turn everything into generic classes and functions which then makes it very difficult for anyone else to figure out what is going on. One reason I like go is it doesn't have all the bells and whistles that give too many choices.
- jerf 6y agoI expect after a flurry of initial excitement, the community will settle on some standards about what it is and is not good for that will tend to resemble "Go 1.0 + a few things" moreso than "A complete rewrite of everything ever done for Go to be in some new 'generic' style".
- mixedCase 6y ago> which then makes it very difficult for anyone else to figure out what is going on Or we can learn to read them. Just treat types like a first class value. You either assign names to types like you do to values, or you can assign a name to a function that returns a type, this being generics.
- systemvoltage 6y ago> or we can learn to read them That's an awful way to think about hard to read code. I could produce the most unreadable one liners you've ever seen in your life. We should condemn that and not blame it on others to "learn how to read".
- ragebol 6y agoYou write code for an audience. In that audience, sit yourself in your current state, yourself a year+ from now, your colleagues (you know their level) and the compiler. With bad luck, your current self i a state pulling your hair out to debug. Think about the audience when you code.
- gowld 6y agoI assume you only program in readable languages like COBOL and AppleScript.
- binwiederhier 6y agoI am glad contracts are being dropped. It was very confusing indeed. Thanks for listening to the community.
- tapirl 6y agoJust the concept name is dropped, the concept itself is still there.
- galkk 6y agoTypical to Go verbose style, but even that is better than nothing (example from the doc) s := []int{1, 2, 3} floats := slices.Map(s, func(i int) float64 { return float64(i) }) Type inference for generic function arguments This is a feature we are not suggesting now, but could consider for later versions of the language.
- daenz 6y agoIn my mind, this generics flip-flop will do no good for the long term survival of Golang. One way to view it is as "listening to the community and changing" but I think a change this big signals a fracture more than an evolution. Think about how much planning and foresight goes into making a programming language, especially one that comes out of a massive top-tier tech company like Google. They deliberately chose not to include generics and (from what I remember when I wrote Go code) spent time + effort explaining away the need for them. Now the decision is being reversed, and it signals to me that they don't know what they're doing with the language, long term. As a developer, why do I want to hitch my carts to a language whose core visions are very clearly not correct or what people want?
- etaioinshrdlu 6y agoOr alternatively, they took forever to do it not because they don't like generics, but because they are super conservative with design and wanted to do it right.
- shanemhansen 6y agoIs there anything about this proposal that would have been surprising to someone 5 years ago? Anything to show for waiting most of the decade other than a decade lost?
- infogulch 6y agoJudging past work by the "obviousness" of the final solution is shallow, juvenile, and dismissive. Every problem is easy when viewed through the lens of of a nearly-complete solution. There have been a wide variety of published proposals for generics in Go [1], each of which seemed plausible but had some insufficiency. Who knows how many proposals were conceived but never left the developer's machine. If it's so damn obvious/you're so brilliant where's your proposal dated Jun 2010 (your 'decade lost') that "solves" generics? [1]: https://github.com/golang/go/issues/15292 https://github.com/golang/go/issues/15292
- randomdata 6y ago
- cybervasi 6y agoAda language had generics since the first 1983 standard. When C++ came about it introduced OOP features that Ada lacked and didn't get for another 12 years when 1995 standard was introduced. C++ users never missed generics for many years and the language became ubiquitous while Ada remained marginalized. What's interesting is that all strongly typed languages have now jumped on the generics bandwagon, which to me shows that being ahead of its time doesn't pay off.
- erik_seaberg 6y agoThe first edition of Stroustrup is the only version without templates (and exceptions). I remember awful macro workarounds for C++ compilers with broken template support, so I think everyone knew that some kind of generics were obviously needed. Ada got this and a few other things right, but it was painfully verbose and the first compilers were so expensive that few seriously evaluated it.
- erik_seaberg 6y agoIf I had to pick a language that got nearly everything right and shouldn't have failed, it'd be Eiffel. But it was also priced more like a truck than a tool until too late (at a time when programmers didn't generally cost six figures!)
- hitekker 6y agoRob Pike is not mentioned in the blogpost or in the sources the authors acknowledge as contributors to this project. What is he up to nowadays?
- ainar-g 6y agoHe still commits code and responds to Github issues occasionally, and I think it's safe to assume that he's still participating in the internal discussions about the design. But most decisions about language changes these days are made by Russ Cox, Ian Lance Taylor, and Robert Griesemer. At least, that's the impression I'm getting.
- hitekker 6y agoThat jives with this article I found: https://evrone.com/rob-pike-interview https://evrone.com/rob-pike-interview > Rob: Although it's far from certain, after over a decade of work it looks like a design for parametric polymorphism, what is colloquially but misleadingly called generics, is coming in the next year or two. It was a very hard problem to find a design that works within the existing language and feels as if it belongs, but Ian Taylor invested a phenomenal amount of energy into the problem and it looks like the answer is now in reach. Sounds like he took a welcomed step back. Hopefully the new leaders can deliver.
- grey-area 6y agoIan Lance Taylor has been involved in the language for a long time, since 2008. Here he is talking about the built-in function append and why it shouldn't really exist in 2017 https://www.airs.com/blog/archives/559 https://www.airs.com/blog/archives/559
- ccktlmazeltov 6y agothat's pretty sad, we probably wouldn't have to deal with generics in Go 2 if he was still around :(
- 6y ago
- albeva 6y agoI feel like Go lost its chance by being way too slow to innovate. From my circle of people who I remember were extremely excited about Go when it first came out - no one really uses it anymore. In our circle it has become a "meh" language. Heck Apple Swift on server is way more exciting than Go these days.
- thomascgalvin 6y agoGo is huge in the Kubernetes world... mainly because both are Google inventions. But almost all of the third-party integration I've seen in k8s has involved Go.
- majewsky 6y agoKubernetes actually started out in Java, and was only rewritten into Go later (before 1.0 though). The choice of Go could also have been influenced by Docker being written in Go (which also meant that some Docker-related libraries were already available for Kubernetes to use).
- sagichmal 6y agoThe super early Java prototype of Kubernetes lived for about a week or two and never saw a public repository. It's kind of misleading to say it "started out in Java".
- zerotolerance 6y agoIt isn't supposed to be an exciting language. It specifically not fancy. Great for teams. Forced style consistency. Clear expectations. Difficult to mis-read compared to most others. Terse, almost rude.
- enahs-sf 6y agoThere is a lot of beauty in go’s simplicity. Very straightforward to reason about what’s going on. I find it much easier on the eyes than java.
- andy_ppp 6y agoI wish they would just add macros instead and then you can effectively code generate at compile time any specific generic-ness that is needed.
- zenhack 6y agoMacros are not a substitute for parametric polymorphism ("generics"). With lisp-style macros you could easily implement something like C++ templates, but that's different in at least one critical way: with C++ templates, the templates are expanded before typechecking, whereas with proper generics, typechecking happens while the type parameters are still opaque. The former has several disadvantages: - It gets you really garbage error messages, because the type errors are usually about something in the body of the template, wherever it tries to do something that the type you substituted doesn't support, rather at the offending call site. - It hurts compile times (above and beyond proper generics), since you need to type check the generic function at every call site, rather than just once. - It makes it easy to break interfaces, because exactly what is required of a type parameter isn't written down anywhere -- it's just whatever the body tries to do with it. (Though it is also true that generics are certainly not a full substitute for macros. I would welcome some mechanism for doing codegen that didn't complicate the build system and was a bit lighter weight than what we have now).
- gpderetta 6y agoC++ templates are not expanded before type checking. Template instantiation is type driven. In fact you can even conditionally expand a template on whether an arbitrary expression typechecks. You wouldn't be able to do it if templates were a different phase. Only early extremely non conforming compilers had macro-like template expansion. Edit: although calling templates type level macros wouldn't be completely wrong. Edit2: a better definition is that templates are type level functions: they take compile time values, types and other type functions and return values, types and type level functions.
- zenhack 6y agoFair enough; I suppose I was oversimplifying. I think the broader point I was trying to make (in addition to the specific downsides I mentioned) still holds though. The Template Haskell paper has some interesting things to say on the nature of C++ templates: https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/meta-haskell.pdf https://www.microsoft.com/en-us/research/wp-content/uploads/...
- cies 6y agoI cant help feeling it is a missed opportunity to add generics to Go this late. A mistake that is copied from earlier languages (C++, Java), a mistake similar to other mistakes Go chose not to solve at it's inception, like: having implicit nulls (C, C++, Java, JS, C#), lack of proper sum types (C, C++, Java, JS) and only one blessed concurrency model (JS). While I think I get the reasons for these decision in theory, make a simple-to-fully-understand language that compiles blazingly fast, I still feel it's a pity (most) these issues where not addressed.
- apta 6y ago> having implicit nulls (C, C++, Java, JS, C#), > lack of proper sum types (C, C++, Java, JS) Incidentally, Java and C# have addressed (or are in the process of addressing) both issues. Both languages/platforms are superior to golang in almost every conceivable way.
- karmakaze 6y agoI'm not aware of any current Java project on Sum types. There is multi-catch for exceptions but no immediate plans I know to use elsewhere.
- apta 6y agoA form of pattern matching and switch expression has already made it to the language as of JDK 14. Those are paving the way for full blown pattern matching and sealed types: https://cr.openjdk.java.net/~briangoetz/amber/datum.html https://cr.openjdk.java.net/~briangoetz/amber/datum.html https://openjdk.java.net/jeps/360 https://openjdk.java.net/jeps/360
- richardwhiuk 6y agoJava aren't fixing nulls, IMHO. They are making it worse.
- apta 6y agoHow are they making it worse? In any case, there already exist solutions in place: https://checkerframework.org/manual/#example-use https://checkerframework.org/manual/#example-use https://github.com/uber/NullAway https://github.com/uber/NullAway
- rowanseymour 6y agoThe only time I get frustrated by the lack of generics in go in trying to get keys from a map... I can't have a single `keys(map[string]T) []string` function.
- vlads_ 6y agoWell, you can :) https://play.golang.org/p/sum21uSy1Ae https://play.golang.org/p/sum21uSy1Ae
- srathi 6y agoThis is an awesome use of the reflect package!
- grey-area 6y agoFor certain values of can.
- vlads_ 6y agoNever said it was a good idea. It's inefficient, unsafe and hard to read but, as far as I can tell any generic function with concrete return types can be written using reflect (and any generic function with generic return types can be written also, it just requires the caller to manually cast from an interface{} to the correct type). So, that's an interesting thing.
- benhoyt 6y agoI started to write one in the "Go 2 playground", but then realized they had that exact example in the draft design: func Keys(type K comparable, V interface{})(m map[K]V) []K { r := make([]K, 0, len(m)) for k := range m { r = append(r, k) } return r } Usage: m := map[int]int{1:2, 2:4} k := maps.Keys(m) // Now k is either []int{1, 2} or []int{2, 1}.
- pjmlp 6y agoCurrently I just want some form of genericity, regardless which one, but I fear we will go through yet another cycle of community feedback and by August 2021 still not there. However not to be just negative, I will certainly take the opportunity to provide my positive feedback as well, so looking forward to play with go2go.
- eatonphil 6y agoYeah, glad that work is being done. But surprised to see this status update be that nothing substantial has changed in the last year.
- badrequest 6y agoThey've reworked the draft, written a generics-capable type checker, a translator tool that lets you use the draft in the current version of Go, and published a generics-capable version of the playground. How is none of that substantial?
- djur 6y agoThe Featherweight Go paper also just recently came out, which is an important step: https://arxiv.org/abs/2005.11710 https://arxiv.org/abs/2005.11710
- zenhack 6y agoI'm sympathetic to being somewhat impatient; I'd really like to have generics in Go years ago too. But I'm also glad they didn't just plow ahead with the first draft of the proposal that came out; the way contracts worked was horrible, and the slow deliberative process means that we don't actually have to deal with those mistakes. Unfortunately, good design takes time.
- throwaway894345 6y agoMe too. A bad generics implementation is profoundly worse than no implementation at all. This angers people who have minimal experience with Go and it certainly seems counterintuitive until you understand that the way the community writes their code affects your experience whether it’s just a different paradigm or a conflagration of paradigms, whether it’s a little abstraction or gratuitous abstraction, etc.
- deleted 6y ago[deleted]
- djhworld 6y agoNeat, thrown together Set implementation https://go2goplay.golang.org/p/FffAhV8aLyN https://go2goplay.golang.org/p/FffAhV8aLyN
- coder543 6y agoMight as well use the zero-size struct{} instead of bool, given that you’re not currently using the bool values for anything: https://go2goplay.golang.org/p/9iegVQ2VQCr https://go2goplay.golang.org/p/9iegVQ2VQCr Alternatively, use the bool values and rely on the zero value for missing elements: https://go2goplay.golang.org/p/E7yHQqAPseG https://go2goplay.golang.org/p/E7yHQqAPseG
- bradfitz 6y agoAnd variadic args to NewSet looks a bit nicer yet at the call site: https://go2goplay.golang.org/p/fTp3W9IwuVP https://go2goplay.golang.org/p/fTp3W9IwuVP
- parhamn 6y agoIs there a way to do this without losing range?
- coder543 6y agoThe proposal is, for better or worse, quite clear about not providing operator overloading or anything similar in the near future. You could always offer a method that returns a slice of unique elements, which could then be ranged over.
- djur 6y agoI don't think there's nearly as much of an appetite for operator overloading as there is for an iterator protocol for range. That isn't to say that the latter wouldn't have a lot to argue over (internal vs. external, etc.) but I think the general usefulness of such a thing would be widely accepted by the community once generics are a settled matter, while I doubt that will ever happen for operator overloading.
- adamch 6y agoFinally. Better late than never. I have to write a lot of Go code at $BIGCORP and keep reaching for generic helper functions like Keys or Map or Filter or Contains. This is going to make my code much more readable.
- nemo1618 6y agoWill it really? Old: sum := 0 for _, x := range xs { sum += xs } New: slices.Reduce(xs, 0, func(i, j int) int { return i + j })
- dilap 6y agoYeah no real gain for that case, but for something like filter, definitely a win.
- hombre_fatal 6y agoThat's the most compelling example you could come up with as someone who presumably writes Go? Reversing a slice of T. Copy and pasting this: for i := len(a)/2 - 1; i >= 0; i-- { opp := len(a) - 1 - i a[i], a[opp] = a[opp], a[i] } New: reverse(a) Or generic versions of these: https://gobyexample.com/collection-functions https://gobyexample.com/collection-functions
- adamch 6y agoYep, this is exactly the use case I was talking about.
- TheCoelacanth 6y agoNew: slices.Sum()
- reissbaker 6y agoThis is an argument I've seen played out in other language communities. In the JS/TypeScript world, the current evolving consensus is "most of the functional programming methods improve readability, except reduce, which is usually worse than a for loop." I think the other replies to your comment point out the improvements that non-reduce-based versions of the code would bring, but I wanted to specifically call out reduce as being a pretty awkward function in other languages as well. So I think it's not a strong argument against generics (and the OP didn't mention wanting it in the first place); by and large functional methods like map, filter, reverse, etc are more readable; reduce is the exception that often isn't. I wrote a fair bit of production Go code in my past, and missed many functional programming patterns. Didn't really miss reduce though. I'm glad that it seems like the ones I missed will become possible with this generics proposal. And reduce isn't horribly unreadable, it's just a slight degradation compared to a for loop IMO. And the other functions are a large improvement.
- nemothekid 6y agoI've been writing a lot of Rust lately after writing Go for 7 years now (unrelated, but that is incredibly odd for me to write out. It still feels like that funny new language that came out of Google). I've always said that generics is overhyped (in Go), but I find that I write a lot of generic stuff in Rust that is somewhat surprising. For example we have a JSON API that returns data in the format '{"ok": bool, "data":...}'. In Go I might do something with json.RawMessage and pay for decoding twice, or annotate every struct with Ok/Data. But in Rust I can just have a type ApiResponse<T>. Then I can have functions that operate just on ApiResponse, or ApiResponse<T=Users>. This problem is solvable in Go, but in a different way and with less guarantees. However that power comes at a mental cost, that creeps in C++ as well. I spent more time playing type system golf trying to come up with the optimal type for whatever usecase. In Go I might just "do the work", but in Rust I've turned 5 minute functions into 30 minute api design thought exercises. The jury is out if thats is a good thing or a bad thing. That said, the only feature I'd steal from Rust is sum types and getting rid of null. `nil` interfaces are the only language feature to actually cost me money and Option<T> is just better in every aspect, and Result<T> is much better than err == nil. I'd be perfectly happy with compiler blessed Option and Result types even if the larger language didn't support generics.
- nine_k 6y agoThe cost you pay for appeasing the type system is the cost you're not paying writing more tests around corner cases ("this function never returns null"), debugging segfaults, null pointer exceptions, "attribute not found" errors, memory leaks (lifetimes help here), etc. The type system may not always help you get your code out the door faster, but when you finally ship it, you have much easier time running it.
- whatshisface 6y ago>The cost you pay for appeasing the type system is the cost you're not paying writing more tests around corner cases I have spent a lot of time in Rust getting carried away with type system stuff that is not required for the actual program I am writing. I realize this when I go over it a second time and reduce line counts drastically by replacing my gee-whiz generics with primitive types. This is balanced out by an equal number of times where I've reduced line counts drastically by using the advanced type stuff to reduce the repetition that comes along with using primitives to represent a type that has way more structure than the primitive.
- hashamali 6y agoWhile I’ve learned to work without generics, this is a welcome proposal. Many cases where we’ve been forced to use interface{} + cast could be genercized.
- atombender 6y agoUnlike other commenters, I don't think it's too late to add generics to Go. I'm looking forward to this. My only negative reaction is that throughout these proposals, I've not been a fan of the additional parentheses needed for this syntax. I can think of several syntaxes that would be more readable, potentially at the expense of verbosity.
- hu3 6y agoYou just can't please everyone. I think that there are benefits when taking the time to gather feedback from people who actually use the language and make educated decisions with regards to language features instead of shoving them down in v1.
- meddlepal 6y agoWhat a joke. Go devs spent a decade telling people they were waiting for the right design for Generics to emerge. Finally after a decade they deliver to us... Java-lite generics which are going to require the community to do a massive library ecosystem retooling for next five to ten years similar to how Java felt going from pre 1.5 to 1.5 and beyond. This language is such a frustrating mess at times.
- atombender 6y agoI'm not sure what you expected. With the exception of Ian Lance Taylor, the Go team has expressed skepticism (and, in the case of Rob Pike, outright disdain) about generics since day one. To anyone who has followed the Go development process at all, this proposal will not be a surprise. The previous proposal was also extremely conservative. Personally, I don't see any other way. Going full-blown generics in the style of Rust/Haskell/OCaml, for example, would drastically alter the language. This is closer in scope to, say, Modula-3.
- meddlepal 6y agoI'm more frustrated that it took a decade to get to this point. Not that it is not more powerful.
- ccktlmazeltov 6y agoThen why do you use it? I'd rather have no generics in Go, maybe you can try Rust?
- meddlepal 6y agoBecause I have a job that pays good money working in Go. Doesn't mean I have to be happy with it.
- ccktlmazeltov 6y agoInteresting, the reason they chose Go is probably due to its no BS aspect. But forcing to make java/C++ people work with it actually makes the language worse. Interesting.
- kodablah 6y agoThis is going to give rise to a utility-belt of sorts, which is what I'm really looking forward to. There are many collections and common utilities that we've all been hand-writing for a while (e.g. waiting for Set(string) instead of map[string]struct{}, or a TreeMap(string, Thing) instead of maintaining sort order separate or using reflection for an existing lib). > Methods may not take additional type arguments While I can fathom the complications that arise, I'm hoping they can work past this restriction by launch.
- renewiltord 6y agoPrefer no generics in Go. Like Go simplicity. Don't want all languages to merge into single grey good form. Want strong trade-offs made.
- shpongled 6y agoWhy use many words when few do?
- Strom 6y agoFor one, everyone isn't fluent in English. I guess it could also be a low bandwidth input situation.
- lanius 6y agoI'm pretty sure shpongled is just quoting Kevin from The Office: https://www.youtube.com/watch?v=VvPaEsuz-tY https://www.youtube.com/watch?v=VvPaEsuz-tY
- ccktlmazeltov 6y agolonger version: https://www.youtube.com/watch?v=_K-L9uhsBLM https://www.youtube.com/watch?v=_K-L9uhsBLM
- conroy 6y agoHere's a four-line replacement for the various `sql.Null*` types in the standard library. type Null(type T) struct { Val T Valid bool // Valid is true if Val is not NULL } Here's what it looks like in practice: https://go2goplay.golang.org/p/Qj8MqYWWAc3 https://go2goplay.golang.org/p/Qj8MqYWWAc3
- sethammons 6y agoneat example, thanks. It gives you a generic Null type that has a bool is-valid field. Very similar to the sql.Null{String,Int} types, but you don't have to declare each one. Kinda the point of generics :)
- tandr 6y agoNice. But I need to retrain myself to read Go code again, because func Make(type T)(v T) Null(T) { } looks really confusing and unreadable to me - too many brackets...
- IshKebab 6y agoI agree. I assume they avoided the standard <> brackets to keep things simple, but really it just makes it harder to parse visually.
- deleted 6y ago[deleted]
- peter_l_downs 6y agoLooks like a big step in the right direction. The biggest pain is that methods cannot contain additional types, which prevents the definition of generic containers with a map method like func (c Container(T)) Map(transform(type V)(T) V) Container(V) if you want to see what `Result(T)` and `Option(T)` look like under this proposal, check out a very stupid implementation here https://go2goplay.golang.org/p/dYth-AQ0Fru https://go2goplay.golang.org/p/dYth-AQ0Fru It's definitely more annoying. But, as per https://go.googlesource.com/proposal/+/refs/heads/master/design/go2draft-type-parameters.md#methods-may-not-take-additional-type-arguments https://go.googlesource.com/proposal/+/refs/heads/master/des... it looks like maybe they will allow additional type parameters in methods, which would be REALLY nice.
- jasondclinton 6y agoThis should be the top comment: constructive criticism with a working example of how a simple sum-type-Rust-like-thing would be implemented.
- whateveracct 6y agoYou can improve the non-method syntax slightly by using option.Map in Go style. But it still isn't as nice as a method. I think type parameters of methods will definitely get added since it's so standard and if anything more confusing to not have them.
- peter_l_downs 6y agoYeah, it's a little nicer that way, but methods would be ideal IMO.
- rogpeppe1 6y agoThere's no need to use the pointer in there; you could just use an ok bool instead (saving the indirection): https://go2goplay.golang.org/p/4hr8zINfRym https://go2goplay.golang.org/p/4hr8zINfRym I think it's interesting to observe that using the Result type is really not that much different from using a multiple return value - it's actually worse in some ways because you end up using "Unwrap" which can panic.
- ccktlmazeltov 6y agoThis is really sad, generics add a ton of complexity and get abused over and over in many codebases. Sure if you have a competent team then you can stop the bleeding, but it'll be all over the place in your dependencies. Every developer who discovers generics has this urge to be clever and write things that are hard to read and maintain. Reading a Go codebase on the other hand is really a pleasure, this is due to the simplicity and straight-to-the-point aspect of the language, as well as the compile times. I really think Go had found a no-bullshit niche that it catered really well to, and I'm scared of what Go post-generics will look like. Are there any other languages like Go that have no plans to move to generics? PS: beautiful quote from rob pike: https://news.ycombinator.com/item?id=6821389 https://news.ycombinator.com/item?id=6821389
- jaredtn 6y agoAgree that it adds complexity - nobody wants a repeat of Java enterprise apps from years ago. In the world of scientific computing and recommendation systems, it's a godsend. Writing your own sort function and your own min function gets old, and you're tempted to return to the world of Python and NumPy. This brings Go onto much better footing with some basic generics functionality.
- typon 6y ago"My late friend Alain Fournier once told me that he considered the lowest form of academic work to be taxonomy" That's really unfortunate. I think a lot of the point of science (maybe even the entire point?) is to model the world and create taxonomies. Instead of being considered "busy work" or tedious, it should be held in the highest regard. Similar reasoning is why I think Rob Pike's opinion on generics is exactly wrong.
- djur 6y agoI actually had never read that Rob Pike quote and it's really baffling to me. It's not about generics at all! It's hard not to read it as saying "generics are recommended to me by the same weirdos who like inheritance, and I don't like inheritance, so generics are BS too".
- 6y ago
- pansa2 6y agoIt looks like this will make Go a significantly more complex language. Despite Go's success over the last 10+ years, have its designers concluded that the language is too simple? Is there no place for a simple statically-typed language like current versions of Go? If not, then for those of us who particularly want a simple language, is dynamic typing the only option?
- djur 6y agoThis is a very conservative, simple implementation of generics. The vast majority of its impact will be to make the code devs deal with on a day-to-day basis simpler to use. It will reduce the necessity for parts of Go that are already complicated, like go gen and reflection.
- Animats 6y agoThis looks like a good, minimal implementation of generics. It's mostly parameterized types. Go already had parameterized types, but only the built-ins - maps and channels. Like this. var v chan int Somewhat surprisingly, the new generic types use a different syntax: var v Vector(int) Do you now write v := Vector(int) or v := make(Vector(int)) Not sure. The built-in generics now seem more special than they need to be. This is how languages acquire cruft. The solution to parameterized types which reference built-in operators is similarly minimal. You can't define the built in operators for new types. That's probably a good thing. Operator overloading for non-mathematical purposes seldom ends well. They stopped before the template system became Turing-complete (I think) which prevents people from getting carried away and trying to write programs that run at compile time. Overall, code written with this should be readable. C++ templates have reached the "you are not supposed to understand this" point. Don't need to go there again.
- throwaway894345 6y agoPresumably you write v := Vector(int){} Or v := make(Vector(int)) Just like with unparameterized types.
- deleted 6y ago[deleted]
- kortex 6y agoIt's still fleshing out the details, and this is a great point to bring up. I suspect it may be a shim to make the parser more manageable. I for one would love to see all generics harmonize with the existing syntax for map, chan, etc.
- dvirsky 6y agoEven the current syntax is a bit non coherent. Would you go with "Vector[int]" a la map, or with "Vector int" a la chan? I think both considered the proposed syntax is actually better.
- kardianos 6y agoThe draft design document is very readable too: https://go.googlesource.com/proposal/+/refs/heads/master/design/go2draft-type-parameters.md https://go.googlesource.com/proposal/+/refs/heads/master/des... I'm rather excited..
- shp0ngle 6y agoIs there a reason Go is not using <> instead of ()? So instead of func Print(type T)(s []T) { for _, v := range s { fmt.Print(v) } } we would get func Print<T>(s []T) { for _, v := range s { fmt.Print(v) } } ?
- shp0ngle 6y agooh they address it themselves in TFA https://go.googlesource.com/proposal/+/refs/heads/master/design/go2draft-type-parameters.md#why-not-use-the-syntax-like-c_and-java https://go.googlesource.com/proposal/+/refs/heads/master/des...
- masklinn 6y agoThe angle brackets increase parsing complexity because `>` is a valid standalone operator (which neither ] nor ) is, usually) making the grammar ambiguous: given Foo<Bar> You still don’t know whether this is a bunch of comparisons or a parametric type, meaning you need either feedback from the type checker into the parser or possibly unbounded lookahead before you can even generate a parse tree.
- st1ck 6y agoApart from other reasons, it just looks ugly. Any kind of braces is better than <>.
- baby 6y agoThis saddens me :( as a reviewer of code I found Golang to be extremely easy to read due to the lack of expressiveness. The most secure codebases I've seen are all in Golang (or are written by strong engineers).
- kevlar1818 6y agoMaybe it's because I'm a newcomer to Go, but I'm surprised by all of the shade being thrown in the comments here. I think the design doc presents a clean and simple way to implement generics in Go -- and therefore it's very much in keeping with the spirit Go. I especially like the constraints system. Constraining generic types via interfaces just feels "right" for the language. It leans on a familiar mechanism with just enough leverage. I'm not without concerns, but I'm struck by conflicting thoughts: I share the worry that implementing generics will negatively affect Go program readability which Go developers (rightfully) covet; when you have a hammer, everything looks like a nail. And yet, I also worry that the Go community is at risk of analysis paralysis on iterating the language in meaningful ways; the novel and innovative spirit that created Go must be harnessed to propel it into the future, lest it dies on the vine.
- dokka 6y agoI won't use GO until they add generics. Hopefully they'll add them someday. I can wait as long as it takes.
- jeffdavis 6y agoThere's a tension in languages between making it easier to write many layers of libraries versus making it easier to write applications. Languages that want libraries that go ten layers deep need to carefully manage things with sophisticated type systems and compilers that can cut through and inline all the abstractions so it still runs fast. Think rust, C++, haskell (all of which, not by coincidence, have long compile times). Languages for writing applications and solving problems tend to have a flatter dependency tree and wider standard library (often including practical functionality like JSON parsers). Think erlang, Perl, PHP. I used to think Go was in the latter category, but it seems to be getting pulled into the former category. Perhaps that's a reflection of Go developers using more layers of abstraction than they have in the past?
- politician 6y agoGo benefits from a continuous flattening phenomenon due to how interfaces and types interact. The determination of whether a type implements an interface is done at the interface use site rather than the type declaration site (as in C#, Java, etc.) I don't think Go developers are using more layers of abstraction than they have in the past; they aren't smarter or more sophisticated than they were before -- RAFT was written in Go, for example. Your observation is a good one, however; are there other ways that Go idiomatically flattens type hierarchies?
- jeffdavis 6y ago"they aren't smarter or more sophisticated than they were before" To be clear, I was not suggesting that more layers of abstraction reflect more sophisticated developers. Just that more layers require something in the language to help developers manage those layers without going insane. There's a lot of wisdom in choosing a flatter approach when it makes sense.
- politician 6y agoIn your opinion, what languages do have effective tools for managing high towers of abstraction? I'm genuinely curious, having spent many nights building ontologies.
- anonfunction 6y agoI like this, here's a Sum function that supports all number types: https://go2goplay.golang.org/p/hPDnvRa-Bif https://go2goplay.golang.org/p/hPDnvRa-Bif
- rosshemsley 6y agoA litmus test I'm excited about is writing a less clunky linear algebra / numerical optimisation package. Gonum is good, but it can feel like a lot of the powerful abstractions in numpy and Eigen are difficult to replicate. Whilst numpy and Eigen do "turn the magic up to 11" just a bit too much for my liking, I do like the idea of things like this: interface Scalar() { type float float32 int int32 int64 } type DenseMatrix(type T Scalar) [][]T func Identity(type T Scalar)(int size) DenseMatrix(T) etc.
- shp0ngle 6y agoCan `Option(type Value)` and some sort of `option.Unwrap` now totally replace `(value, error)` and `err != nil` checks? :D
- suzuki 6y agoNow the abstract sequence type of "LINQ in Go" https://github.com/nukata/linq-in-go https://github.com/nukata/linq-in-go can be written as type Enumerator(type T) func(yield func(element T)) and the "Select" method can be written as func (loop Enumerator(T)) Select(f func(T) T) Enumerator(T) { return func(yield func(T)) { loop(func(element T) { value := f(element) yield(value) }) } } You can call this method with type-safety as follows. Yay! func main() { squares := Range(1, 3).Select(func(x int) int { return x * x }) squares(func(num int) { fmt.Println(num) }) } // Output: // 1 // 4 // 9 See https://go2goplay.golang.org/p/b0ugT68QAy2 https://go2goplay.golang.org/p/b0ugT68QAy2 for the complete code. And, for generality, you should write the method actually as follows. func (loop Enumerator(T)) Select(type R)(f func(T) R) Enumerator(R) { return func(yield func(R)) { loop(func(element T) { value := f(element) yield(value) }) } } However, you will get the error message then: type checking failed for main prog.go2:17:33: methods cannot have type parameters According to https://go.googlesource.com/proposal/+/refs/heads/master/design/go2draft-type-parameters.md#methods-may-not-take-additional-type-arguments https://go.googlesource.com/proposal/+/refs/heads/master/des... this seems an intended restriction: > Although methods of a generic type may use the type's parameters, methods may not themselves have additional type parameters. Where it would be useful to add type arguments to a method, people will have to write a suitably parameterized top-level function. > This is not a fundamental restriction but it complicates the language specification and the implementation. For now, we have to write it as https://go2goplay.golang.org/p/mGOx3SWiFXq https://go2goplay.golang.org/p/mGOx3SWiFXq and I feel it rather inelegant. Good grief
- mkchoi212 6y ago> Second, we know that many people have said that Go needs generics, but we don’t necessarily know exactly what that means. Seems like the go authors are still bent on the idea that generics are really not necessarily and that there is no such problem that can only be solved by generics. Then is the generic drafting only a thing because they have been pressured into it by the community? I wonder why Rob Pike one day decided that it’s okay to change a language he almost vowed to never change after the initial release.
- woah 6y agoWhat’s funny is that the stdlib makes extensive use of generics
- rmdashrfstar 6y ago"For me and not for thee"
- kerkeslager 6y agoThe anti-generics folks in the Go community are pretty prevalent still--meanwhile the Go community frequently lauds Go's strong type system. I suppose it's possible that these aren't the same people, but it seems more likely to me that many Go users don't know the difference between strong types and static types, and think that all static types are strong types. Without generics, Go does not have a strong type system. It has a type system that verifies just enough to force you to work around it to do things that require generics, meaning that you don't get the benefits of verification because you've worked around it. You get the development speed of a statically-typed language with the type guarantees of a weakly-typed language: the worst of both worlds.
- whateveracct 6y agoThe "we still can't abstract over zero values" section is only really solvable with ad hoc polymorphism (type classes)