6 ms·
Go's updated generic proposal (Contracts)
- simonz05 7y agoThere is some more information in this liveblog from Ian's talk, Generics in Go [1], and the *.go2 files in Robert Griesemer's change list [2] [1]: https://about.sourcegraph.com/go/gophercon-2019-generics-in-go https://about.sourcegraph.com/go/gophercon-2019-generics-in-... [2]: https://go-review.googlesource.com/c/go/+/187317/ https://go-review.googlesource.com/c/go/+/187317/
- tomohawk 7y agoExcellent example of clear and concise writing, introducing a subject.
- azernik 7y agoWhatever you think of Go as a language, its documentation is outstanding.
- grenoire 7y agoHonestly it just reminds me of Rust's traits (granted I didn't read the entite spec.), could this come with operator overloading too?
- owaislone 7y agoIt could in future but this document is staying away from overloading. I doubt Go will ever support it really but this design does not do anything to prevent it in future.
- latchkey 7y agoI've been doing some work in Dart/Flutter recently and I'm finding it to be a nice mix of Java/JavaScript/TypeScript/Golang. It has generics which work pretty well, although I've already found a very small bug in it [1]. Initial reading of this document makes me feel it is really over complicated compared with Dart. [1] https://github.com/dart-lang/sdk/issues/37626 https://github.com/dart-lang/sdk/issues/37626
- proyb 7y agoWhich part is overcomplicated compared with Dart?
- latchkey 7y agoOne thing I really like about Dart is the lack of interface objects, they are implicit. The `contract` proposal feels like having to write interfaces. The inference in Dart is really nice to work with as the compiler gets it right most of the time. The other thing is the documentation is really easy to grok and come up to speed on: https://dart.dev/guides/language/language-tour#generics https://dart.dev/guides/language/language-tour#generics https://dart.dev/guides/language/sound-dart https://dart.dev/guides/language/sound-dart Edit: Additionally, mocking (with Mockito-Dart) becomes trivial, which is great for unit testing: class Thing { String boo; } class MockedThing extends Mock implements Thing {} when(thing.boo).thenReturn('ack');
- antpls 7y agoI have knowledge in Python and never developed in Go, so I can't comment the Design choices. On the form, in my humble opinion, the PEP style is easier to read : presenting rational and constraints before the proposed solution. It would mean moving (and a bit of rewording) "Discarded ideas", "Comparison with Java", "Comparison with C++" before "Design" and after "Background". As a reader, I prefer to be presented with the problem first (with the constraints and previously explored ideas), then be presented the logical, "obvious", proposed solution.
- tapirl 7y agoIt is not a proposal, it is a draft. The new draft improves the contract part. But generic declaration part still looks some verbose. There are many repetitiveness, such as the Map example: https://github.com/golang/proposal/blob/4a54a00950b56dd0096482d0edae46969d7432a6/design/go2draft-contracts.md#containers https://github.com/golang/proposal/blob/4a54a00950b56dd00964... func New(type K, V)(compare func(K, K) int) *Map(K, V) func (m *Map(K, V)) Insert(key K, val V) bool func (m *Map(K, V)) find(key K) **node(K, V) func (m *Map(K, V)) Insert(key K, val V) bool func (m *Map(K, V)) Find(key K) (V, bool) func (m *Map(K, V)) InOrder() *Iterator(K, V) And I didn't find how to write a contract which requires a type must have some specified fields in this draft.
- antpls 7y agoI would believe Generics are highly reusable code, you shouldn't have to write and read them often. The verbosity you lost in those few lines are earned every time another piece of code use them. Also you cannot just criticize without also proposing a solution :)
- suprfnk 7y ago> Also you cannot just criticize without also proposing a solution :) Why not? There can be valid criticism without there necessarily being a better solution. That's actually the whole story of generics in Go. Countless proposals, ideas, and criticism. So far, there is no solution.
- namelosw 7y agoGenerics are highly reusable is true. But people don't read and write them often because of the language design. Most Hindley Milner typed languages like ML and Haskell by default are generic by default and it's not harder or more complex than non-generic code. Thinking of a function 'swap'. The signature should just be swap : (a, b) -> (b, a) instead of swap: <T, U>(x: (T, U)) => (U, T). The language design in most of languages which discourage people using generics. In fact, non-generic code usually introduce couplings to the argument type, making things harder to change, and violates the least power principle.
- baby 7y agoI wish there was a way to have generics without: * letting people being able to abuse them. C++ cough cough. * making it clear to people reading the code what is happening. I’ve noticed a few things: * associated types in Rust are much clearer than generics * one letter generics are “overly generic” and do not describe enough. * the declaration of the type really adds verbosity So what can a language do? 1. Maybe change the syntax to this one: func eat(food []generic.Type) Or func eat(food []g::type) Or something that doesn’t involve adding more <> or () 2. Forbid one letter generic or force a description of the generic or even better: force listing all the types that are currently using this generic NEXT to the generic! g.type -> {egg, bacon} func eat(food []g.type) But then you can’t use a generic from another package... but maybe it’s a good limitation? Or force a generic to have a description, which is what golang is doing with interfaces. The problem is that we can’t combine difference interfaces like in Rust/ocaml
- protomolecule 7y ago"or even better: force listing all the types that are currently using this generic" This is a bad idea. Imagine a generic hash map, we surely want it to work with any value type.
- baby 7y agoTrue. I’m trying to find a solution to the biggest problem of generics which is imo that you can’t understand how it’s being used when reading one. It’s fine if the function doesn’t do much. But if it’s nesting generics, or doing anything complex, then not using a union of interfaces make it really hard to understand code. I’d like if Golang would add unions of interfaces. But generics? I’m not sure if it’s a good idea. Or maybe if you import a package that have some generic functions, you would need to add a declaration that list what the types using these generics are. Import “stuffWithGeneric{ thing(K, V) -> (egg, bacon), thing(K, V) -> (int, string), }”
- protomolecule 7y agoImagine you have a non-generic function, for example, `parseJsonData(string)`, how would you understand how it is being used? It can be called with all sorts of input. Is the problem you are describing different?
- threeseed 7y agoIt is just me or do contracts look a lot like type classes.
- choeger 7y agoSshhhht! Industrial players don't like to hear that type systems are a thoroughly mapped space. They like to think that their design is different and does not adhere to the laws of type theory. It is also more fun to watch them struggle essentially reinventing research papers from 20+ years ago. Edit: yes, I am exaggerating a little, but I find it really amazing how PL design is in practice so removed from its theoretical foundations.
- stefano 7y ago> reinventing research papers from 20+ years ago The first(?) paper on type classes, "Parametric overloading in polymorphic programming languages", is from 1988, so they're reinventing things from at least 31 years ago. I guess in 2050 Go will catchup with today's state of the art.
- steinuil 7y agoI don't understand what's the difference between single-parameter contracts and interfaces. Aren't contracts only useful when there's two or more type parameters involved? Edit: didn't read through the whole thing, I guess contracts can do things that interfaces don't. I think the overlap still makes things a bit awkward though.
- misrab 7y agoIf what Generics fundamentally solve is having to type out an almost identical function for many types, why not just have macros?
- YawningAngel 7y agoI think most people would agree that templates are more complicated than generics
- MrBuddyCasino 7y agoI don’t quite get what contracts are needed for? This func Print(type T)(s []T) could be written as func Print(type T implements SomeInterface)(s []T) What am I missing?
- hundt 7y agoYou're probably not still looking for an answer, but since I tried to work through this question myself I will answer it, if only for my own benefit: See the "Mutually referencing type parameters" example. [0] Ignoring the issue of generic types vs functions, suppose you wanted to do shortest path as a fuction using the Node and Edge types described. You could try to write something like func ShortestPath(type N implements Node, E implements Edge)(from, to N) []E but how would it be implemented? Type N only promises that it it implements the Node interface which is just Edges() []Edge but those Edges might not be concrete type E. So instead you must resort to func ShortestPath(from, to Node) []Edge and use type assertions, which is where we were before generics. The contracts allow you to constraint the relationship between the concrete types N and E, enabling callers to work with concrete types directly. [0] https://github.com/golang/proposal/blob/4a54a00950b56dd0096482d0edae46969d7432a6/design/go2draft-contracts.md#mutually-referencing-type-parameters https://github.com/golang/proposal/blob/4a54a00950b56dd00964...
- MrBuddyCasino 7y ago> You're probably not still looking for an answer On the contrary! I think I got it, thanks. Not sure which version is simpler though, I've certainly never hit the "Mutually referencing type parameters" issue before. I guess using concrete types and avoiding vtable lookups is an advantage that matters to Go?
- hundt 7y ago> I've certainly never hit the "Mutually referencing type parameters" issue before. I don't think I have either, but according to that document supporting this use case was considered a minimum requirement for generics. I don't know that much about generics but maybe it comes up more often than we realize. > I guess using concrete types and avoiding vtable lookups is an advantage that matters to Go? It avoids the vtable lookups and also, in cases like the mutually referencing type parameters, provides compile-type type-checking, which you don't get with the interface-only solution. I'm also not sure how your proposed solution extends to parameterized types. Certainly a central motivation of generics is make something like LinkedList<T> possible.
- johnisgood 7y agoFor a second I thought it was related to {pre,post}-conditions.