blob: 6caa70cfc7a1020b7639d0b1beb62346c1b6b19f [file] [log] [blame] [view]
Andrew Bonventrefde42b62018-08-28 09:56:58 -06001# Go 2 Generics Feedback
2
3This page is meant to collect and organize feedback about the Go 2 [contracts (generics) draft design](https://go.googlesource.com/proposal/+/master/design/go2draft-generics-overview.md).
4
5Please post feedback on your blog, Medium, GitHub Gists, mailing lists, Google Docs, etc. And then please link it here.
6
7As the amount of feedback grows, please feel free to organize this page by specific kind of feedback.
dotaheor1ef8b1d2018-09-09 00:48:21 -04008- dotaheor, "[Combine contract and code tegother and view generic as compile-time calls with multiple outputs](https://gist.github.com/dotaheor/4b7496dba1939ce3f91a0f8cfccef927)", September 2018
mr. whythat584ee572018-09-08 11:35:33 +03009- mrwhythat, "[Go 2 generics draft notes](https://gist.github.com/mrwhythat/f5f2e1ea2bb9869082da55529586d972)", September 2018
Aleksei Pavliukov3e90e832018-09-08 01:01:58 +030010- Aleksei Pavliukov, "[Extend type and func keywords](https://github.com/a5i/go-proposal/blob/master/generics.md)", September 2018
韩拓adaaf162018-09-08 00:36:23 +080011- Han Tuo, "[Generic as a kind of types -- type T generic {int, float64}](https://gist.github.com/hantuo/574aeda064c18eb69aa6806fbb259510)", September 2018
4ydx1a17d9c2018-09-06 10:04:14 +090012- Nate Finch, "[Go2 Contracts Go Too Far](https://npf.io/2018/09/go2-contracts-go-too-far/)", September 2018
Roger Peppe517e64b2018-09-05 20:10:55 +010013- Roger Peppe, "[Go Contracts as type structs](https://gist.github.com/rogpeppe/7ea0cb6037aa520934257bf88a1012c5)", September 2018
14- Roger Peppe, "[Go contracts use case: generic mgo](https://gist.github.com/rogpeppe/cbbaf2521749717137625e33ba203eed)", Septembr 2018
Michael Stapelberg518f1732018-09-05 08:25:21 +020015- Axel Wagner, "[Scrapping contracts](https://blog.merovius.de/2018/09/05/scrapping_contracts.html)", September 2018
16
Ali Altun28503222018-09-05 02:22:58 +020017- Matt Sherman "[Generics as builtin typeclasses](https://clipperhouse.com/go-generics-typeclasses/)", September 2018
Ali Altunac8839a2018-09-05 02:22:28 +020018
Roger Peppeaf5ee222018-09-04 11:29:43 +010019- Roger Peppe, "Go generics at runtime", [Part 1](https://gist.github.com/rogpeppe/f9216e5f2b1c99fc13108825dbda6181), [Part 2](https://gist.github.com/rogpeppe/9fa9a267472fb80e9ddc4a940aa26e14), September 2018
20
21- Roger Peppe, "[Operator overloading](https://gist.github.com/rogpeppe/0a87ef702189689201ef1d4a170939ac)", September 2018
22
Kevin Gillette7fa915d2018-09-03 23:37:38 -060023- Kevin Gillette, "[Regarding the Go 2 Generics Draft](https://medium.com/@xtg/regarding-the-go-2-generics-draft-39f7815be89)", September 2018
24
peter-mckenzie89e60702018-09-04 08:02:27 +120025- Peter McKenzie, "[Alternative generics syntax](https://gist.github.com/peter-mckenzie/5cc6530da1d966e743f4a39c150a6ac2)", September 2018
26
TedSingerab47e102018-09-03 11:30:17 -040027- Ted Singer, "[The design goal for syntax is to help humans read](https://gist.github.com/TedSinger/9ab1857bdd00d1f3523911362380f901)", September 2018
K. Alex Mills1acae202018-09-02 16:47:03 -050028
29 - Roger Peppe, "[Revised generics proposal](https://gist.github.com/rogpeppe/45f5a7578507989ec4ba5ac639ae2c69)", September 2018
30
31 - Jason Moiron, "[Notes on the Go2 Generics Draft](http://jmoiron.net/blog/notes-on-the-go2-generics-draft)", September 2018
32
33 - Steven Blenkinsop, “[Response to the Go2 Contracts Draft Design Auxiliary Types](https://gist.github.com/stevenblenkinsop/7b967bb98f876b99dc15620f9fda9eb1)”, September 2018
34
alanfobe696ae2018-09-06 15:54:46 +010035 - alanfo, "[Suggested amendment to Go 2 generics draft design](https://gist.github.com/alanfo/5da5932c7b60fd130a928ebbace1f251)", September 2018
K. Alex Mills1acae202018-09-02 16:47:03 -050036
37- Arendtio "[Generics in Go inspired by Interfaces](https://gist.github.com/arendtio/77dd4df5f4b19dc69da350648434a88a)", September 2018
38
Liamc0662122018-08-28 22:33:12 -070039 - Liam Breck, “[Please Don't Mangle the Function Signature](https://gist.github.com/networkimprov/7c1f311f26852bc912765e4110af062b)”, August 2018
40
DeedleFake1de36842018-08-29 02:05:40 -040041- DeedleFake, "[Feedback for Go 2 Design Drafts](https://deedlefake.com/2018/08/feedback-for-go-2-design-drafts/)", August 2018
42
Roberto94c8e9a2018-08-29 13:59:07 +020043- Roberto (empijei) Clapis, "[Hard to read syntax](https://gist.github.com/empijei/a9665ac5e3059671be229acee8826798)", August 2018
Robertof76be042018-08-29 11:20:54 +020044
Richard Fliam3fbbd812018-08-29 17:42:29 -060045- Richard Fliam, "[Go2 Generics Let You Construct the Natural Numbers](https://gist.github.com/rfliam/c806a4300aa97f2762295ef97d3e924f)", August 2018
46
emilymaier230baa92018-08-30 00:23:20 -040047 - Emily Maier, "[Getting specific about generics](https://emilymaier.net/words/getting-specific-about-generics/)", August 2018
48
Roger Peppe13c0fdd2018-08-30 11:01:20 +010049 - Roger Peppe, "[Go generics feedback](https://gist.github.com/rogpeppe/2be10112c9d875afc0c85effc5595a09), August 2018
50
阮坤良8e4d5f82018-08-30 23:27:02 +080051 - Ruan Kunliang, "[Package level generics](https://gist.github.com/PeterRK/41d4d3f54b8db55cd616403fd5a389f3)", August 2018
52
Javier Zunzunegui413d9022018-08-30 10:03:06 -070053 - Javier Zunzunegui, "[Compiling Generics](https://gist.github.com/JavierZunzunegui/7032f5846fd255811e7af39bd2c74f38)", August 2018
54
jimmyfrasche6879aaa2018-08-30 11:33:59 -070055 - jimmy frasche, "[Embedding of type parameters should not be allowed](https://github.com/golang/go/issues/15292#issuecomment-417422599)", August 2018
56
William Cotton988976e2018-09-02 18:35:25 +020057 - Some Gophers on go-nuts, “[Unifying Interfaces and Contracts](https://groups.google.com/forum/#!topic/golang-nuts/aw3XQV8k1Vw)”, August 2018
Liam6d4eebc2018-08-28 22:29:09 -070058
Christophe Meessen7eca1792018-09-05 08:36:53 +020059 - Dominik Honnef, "[My thoughts on the Go Generics Draft](http://honnef.co/posts/2018/08/opinions-on-go-generics-draft/)", August 2018
Dominik Honnef28ddbfb2018-09-02 20:22:19 +020060
Dave Cheney70ec1df2018-09-03 16:07:24 +100061 - Dave Cheney, "[Maybe adding generics to Go IS about syntax after all](https://dave.cheney.net/2018/09/03/maybe-adding-generics-to-go-is-about-syntax-after-all)", August 2018
62
Andrew Bonventrefde42b62018-08-28 09:56:58 -060063 - etc.
Dag Sverre Seljebotn3841f012018-08-28 21:07:53 +020064
K. Alex Mills5fc11942018-09-02 16:48:06 -050065## Adding Your Feedback
66
67Please format all entries as below.
68
69- _Your Name_, “[_Title_](#URL)”, _month year_
70
71To make it easier to see new feedback. Please *make a Gist*. And also help to keep the list sorted in reverse-chronological order by including your new entry at the *top* of the list.
Dag Sverre Seljebotn3841f012018-08-28 21:07:53 +020072
73## Quick comments
74
Bodie6307b682018-08-29 11:52:44 -040075 - [Bodie Solomon](https://github.com/binary132): I find the generics design a bit confusing and opaque. Please consider integrating some concepts from [Zig's beautiful comptime functions](https://news.ycombinator.com/item?id=13761571)! The design of Go 2 generics is clever, but I feel it goes against Go's traditional tight coupling between simple runtime semantics and simple syntax. Additionally, one of the biggest problems of Go, which prevents it from being a viable competitor everywhere I might like to use it, is that I cannot be rid of the GC and runtime. It was my strong hope that Go 2 would introduce compile-time-only generics such that I could reliably avoid the use of dynamic interfaces where I don't want them, without relying on codegen. Unfortunately it looks like that will be decided by the compiler without my input. Please, at least, consider giving users the ability to constrain generics to compile-time-only resolution, perhaps as a property of a Contract, rejecting compilation of dynamic types to satisfy the contract.
76
Maxwell Corbin9144ad32018-08-28 12:58:11 -070077 - Dag Sverre Seljebotn: C++ has a huge problem with people abusing metaprogramming ("generics") to do compile-time metaprogramming. I really wished Go had gone down the path of Julia, which offers hygienic macros. Even if it is kept strictly at a compile-time barrier and no run-time code generation, this would at least avoid all the bad tendencies we see in the C++ world that comes from their templating system. Things you can do with generics you can usually pull off with macros too (e.g., `SortSliceOfInts = MakeSliceSorterFunctionMacro!(int)` could generate a new function to sort a slice of integers). Link: https://docs.julialang.org/en/v0.6.1/manual/metaprogramming/
78
79 - Maxwell Corbin: The issues raised in the Discussion and Open Questions section all could be avoided by defining generics at the package rather than the function or type level. The reason for this is simple: types can reference themselves, but packages can't import themselves, and while there are many ways to algorithmically generate more type signatures, you cannot do the same with import statements. A quick example of such syntax might be:
Takuma Ishikawa4e952c22018-08-29 13:37:30 +090080
81 ```go
82 \\ list
83 package list[T]
84
85 type T interface{}
86
87 type List struct {
88 Val T
89 Next *List
90 }
91
92 // main
93 package main
94
95 import (
96 il "list"[int]
97 sl "list"[string]
98 )
99
100 var iList = il.List{3}
101 var sList = sl.List{"hello"}
102
103 // etc...
104 ```
105
106 The syntax in the example is probably needlessly verbose, but the point is that none of the unfortunate code examples from the blog post are even legal constructions. Package level generics avoids the most abusive problems of meta-programming while retaining the bulk of its usefulness.
Maxwell Corbin9144ad32018-08-28 12:58:11 -0700107
Russell Johnston31d12712018-08-28 20:51:02 -0700108 - Andrew Gwozdziewycz: The use of the word `contract` gives me pause due to it overloading "contract" as in [Design by Contract](https://en.wikipedia.org/wiki/Design_by_contract). While the generics use case has some similarities with the "contracts" in DbC if you squint a bit, the concepts are quite different. Since "contracts" are an established concept in Computer Science, I think it would be far less confusing to use a different name like `behavior` or `trait`. The design document also suggests reasons why using `interface` is not ideal, though, Go's contract mechanism seems too obvious an extension of interfaces to disregard so quickly... If it can be done `interface setter(x T) { x.Set(string) error }` and `interface addable(x T, y U) { x + y }` seem quite natural to read and understand.
109
Hajime Hoshif82716f2018-08-29 12:58:25 +0900110 - Russell Johnston: Agreed that it would be great to merge contracts and interfaces. Another way around the operator-naming problem might be to provide some standard interfaces for the operators, with bodies inexpressible in normal Go code. For example, a standard `Multipliable` interface would allow the `*` and `*=` operators, while a standard `Comparable` interface would allow `==`, `!=`, `<`, `<=`, `>=`, and `>`. To express operators with multiple types, these interfaces would presumably need type parameters themselves, for example: `type Multipliable(s Self /* this exists implicitly on all interfaces */, t Other) interface { /* provided by the language */ }`. Then user-written interfaces/contracts could use these standard identifier-based names, neatly sidestepping the issues mentioned in the design document around syntax and types.
Roberto6059b202018-08-29 14:57:35 +0200111 - Roberto (empijei) Clapis: I agree on this and on the fact that it should be clearer where to use interfaces and where to use contracts. Unifying the two would be great, as they try to address overlapping issues.
Kurnia D Wina72b7e32018-08-29 22:53:33 +0700112 - Kurnia D Win: I think `constraint` is better keyword than `contract`. Personally i like `type addable constraint(x T, y U) { x + y }` instead of merging with interface.
Hajime Hoshif82716f2018-08-29 12:58:25 +0900113
Hajime Hoshi52978612018-08-29 13:01:29 +0900114- Hajime Hoshi: I feel like the supposed proposal is too huge to the problems we want to solve listed at https://go.googlesource.com/proposal/+/master/design/go2draft-generics-overview.md . I'm worried this feature would be abused and degrade readability of code. Sorry if I am missing, but the proposal doesn't say anything about `go generate`. Wouldn't `go generate` be enough to the problems?
Stephen Rowlesc831c582018-08-29 11:45:23 +0100115
116- Stephen Rowles: I find the method syntax hard to parse, as a human reading it, it might be clearer to use a different type of enclosing brackets for the type section, e.g.
117
Stephen Rowlesbb469892018-08-29 11:45:49 +0100118 ```
119 func Sum<type T Addable>(x []T) T {
120 var total T
121 for _, v := range x {
122 total += v
123 }
124 return total
125 }
Robertoc46f1692018-08-29 13:55:11 +0200126 ```
yesuu735eb2b2018-09-10 08:20:51 +0800127
128- yesuu: In this example, think of `T` as the parameter name and `type` as the parameter type. Obviously it is more reasonable to put the `type` behind, and contract is followed by `type`, like `chan int`.
129
yesuub7883c32018-09-10 08:24:15 +0800130 ```go
131 func Sum(T type Addable)(x []T) T
yesuu735eb2b2018-09-10 08:20:51 +0800132 ```
133
Roberto6059b202018-08-29 14:57:35 +0200134 - Roberto Clapis: Please read [this section](https://go.googlesource.com/proposal/+/master/design/go2draft-contracts.md#why-not-use-like-c_and-java)
Roberto5e630f62018-08-29 14:59:34 +0200135 - Seems like a bit of a cop-out tbh. It says "in general" which means there must already be exceptions. Go has a nice clear syntax making code simple to read and easy for teams to collaborate. I think it would be worth making the parser more complicated for the sake of making the code readability better. For large scale and long running project readability of the code, and hence maintainability, is king
seebs12d6f0f2018-08-29 10:18:29 -0500136 - What about [this](https://gist.github.com/empijei/a9665ac5e3059671be229acee8826798)
137
sean-qf6bb2fc2018-08-29 17:24:48 -0700138- Seebs: [Feedback a bit long to inline](https://gist.github.com/seebs/8f943b8b15a8c63c28c7f6f4e5ca6c53), August 2018. Summary basically "I would like a way to specify one contract for each of two types rather than one contract for both types", and "I would prefer `map[T1]T2` to `t1var == t1var` as a canonical form of "T1 must be an allowable map key".
139
seebsd2f1bde2018-09-01 15:31:35 -0500140- Seebs: [What if contracts *were* just the type-parametric functions?](https://github.com/seebs/notes/blob/master/generics_go2.md). (Sep 1, 2018)
141
sean-q1b50aad2018-08-29 21:07:17 -0700142- Sean Quinlan: I find the contract syntax quite confusing. For something that is supposed to defined exactly what is needed and will be part of the documentation of an api, it can contain all sorts of cruft that does not impact the contract. Moreover, to quote from the design: "We don’t need to explain the meaning of every statement that can appear in a contract body". That seems like the opposite of what I would want from a contract. The fact one can copy the body of a function into a contract and have it work seems like a bug to me, not a feature. Personally, I would much prefer a model that unifies interfaces and contracts. Interfaces feel much closer to what I would like a contract to look like and there is a lot of overlap. It seems probable that many contracts will also be interfaces?
Nodir Turakulov4e84f172018-08-29 20:33:51 -0700143
Nodir Turakulove87d7662018-08-30 07:43:41 -0700144- Nodir Turakulov: Please elaborate
Nodir Turakulov4e84f172018-08-29 20:33:51 -0700145 > Packages like container/list and container/ring, and types like sync.Map, will be updated to be compile-time type-safe.
146
147 and
148
149 > The math package will be extended to provide a set of simple standard algorithms for all numeric types, such as the ever popular Min and Max functions.
150
Nodir Turakulove87d7662018-08-30 07:43:41 -0700151 or ideally add a section about transition/migration of existing types/funcs to use type polymorphism.
Nodir Turakulovf855db22018-08-30 00:57:32 -0700152 FWIU adding type parameter(s) to an existing type/func most likely breaks an existing program that uses the type/func.
153 How exactly will `math.Max` be changed?
Nodir Turakulov4e84f172018-08-29 20:33:51 -0700154 Is the intention to make backward-incompatible changes and write tools to automatically convert code to Go2?
155 What is the general recommendation for authors of other libraries that provide funcs and types that currently operate with `interface{}`?
Ward K Harold69a26e62018-08-30 12:17:46 -0500156 Were default values for type parameters considered? e.g. type parameter for `math.Max` would default to `float64` and type parameter for `"container/list".List` would default to `interface{}`
157
Ole Begemann561db2552018-08-30 19:36:28 +0200158- Ward Harold: If only for the sake of completeness the [Modula-3](https://www.cs.purdue.edu/homes/hosking/m3/reference/generics.html) generics design should be incorporated into the [Designs in Other Languages](https://go.googlesource.com/proposal/+/master/design/go2draft-generics-overview.md#designs-in-other-languages) section. Modula-3 was a beautiful language that sadly got introduced at the wrong time.
159
Ole Begemannb9fd0de2018-08-30 19:56:15 +0200160- Ole Begemann: You write on the [Generics Overview page](https://go.googlesource.com/proposal/+/master/design/go2draft-generics-overview.md): "Swift added generics in Swift 4, released in 2017." This is not true. Swift has had generics since its first public release in 2014. Evidence (just one example of many): [a transcript of an Apple developer talk on Swift from WWDC 2014](https://asciiwwdc.com/2014/sessions/404) that talks at length about Swift's generics features.
161
Kevin Gillettec277be02018-08-30 21:31:22 -0600162 This is also incorrect: "`Equatable` appears to be a built-in in Swift, not possible to define otherwise." The `Equatable` protocol is defined in the Swift standard library, but there's nothing special about it. It's totally possible to define the same thing in "normal" code.
163
164- Kevin Gillette: correction for "Contracts" Draft, as of 30 August 2018
165
Adam Ierymenko90070a72018-08-31 09:02:46 -0700166 The one instance of `check.Convert(int, interface{})(0, 0)` should instead be `check.Convert(int, interface{})(0)` or provide an explanation as to why it the function should take two zeros instead of one.
167
DeedleFake13ef1a52018-08-31 15:08:06 -0400168- [Adam Ierymenko](http://adamierymenko.com): I have an idea for doing limited operator overloading in Go that might make this proposal more useful for numeric code. It's big so [I stuck it in a Gist here](https://gist.github.com/adamierymenko/a03a62da1513a8cc2ac4dfac81b44a9f).
jimmyfrascheb9bb3aa2018-08-31 21:51:48 -0700169 - DeedleFake: I completely agree with the arguments against operator overloading, and I'm quite glad overall that Go doesn't have it, but I also think that the inability to resolve the difference between `a == b` and `a.Equals(b)` via a contract is the biggest problem with the draft design as it currently stands. It means that you'd still wind up writing multiple functions for a fair number of things. Try writing a binary tree, for example. Should you use a contract with `t < t` or `t.Less(t)`? For a sum function, should you use `t + t` or `t.Plus(t)`? I definitely want a solution that doesn't involve operator overloading, though. Maybe there could be a way to specify an adapter that basically says `if a type T, which satisfies contract A but not B, is used for a parameter constrained by contract B, apply this to it in order to get it to satisfy contract B`. Contract B could require a `Plus()` method, for example, while contract A requires the use of `+`, so the adapter automatically attaches a user-specified `Plus()` method to `T` for the duration of its use under that contract.
Adam Ierymenko51e52732018-09-01 16:56:21 -0700170 - Something that might work with this proposal is an `equal(a, b)` builtin that uses `a.Equals(b)` if it exists and `a == b` otherwise, failing to compile if the type is incomparable (and likewise for other operators). It's too weird to seriously consider but it would work with contracts and allow dodging the asymmetry between types that have operators and those that cannot without introducing operator overloading —jimmyfrasche
emetko50600782018-09-03 23:34:47 +0200171 - Another idea would be explicitly overloadable operators: `a + b` is not overloadable, but `a [+] b` can be overloaded. It will use normal + for primitive types, but will use `Operator+()` etc. for objects if those are present. I really do think that generics without some sane form of operator overloading or something like it are a lot less useful to the point that you might as well not even do it. -Adam Ierymenko (original poster)
172- Eltjon Metko: How about specifying the contract after the type identifier inside the function Parameters? This way it can be inferred what T is and we can eliminate the first group of parenthesis.
emetkof1e5b8f2018-09-03 23:36:09 +0200173```
emetko50600782018-09-03 23:34:47 +0200174func Sum(x []T:Addable) T {
175 var total T
176 for _, v := range x {
177 total += v
178 }
179 return total
emetkof1e5b8f2018-09-03 23:36:09 +0200180}
Tristan Colgate-McFarlaned4023992018-09-06 12:36:03 +0100181```
182- Tristan Colgate-McFarlane: After going back and forward for a while, I've come down in favour of the proposal largely as is. A limited syntax for contracts might be preferable, but I believe it should allow referencing specific fields (not just methods as some have proposed). If anything can be done to make compatible interface and contracts inter-use easier, that would also be nice (though I think maybe no additional specifications are needed. Lastly, I think it is worth considering deprecating interface types. Whilst drastic, contracts essentially also allow specifying behaviour. Any contract restrictions that limit that (such as refering to other types within the package), should probably be lifted. contracts appear to be a strict superset of interfaces, and I am generally against having two overlapping features. A tool to aide in writing interaces should also be considered.