blob: ed826b6e9c0fc567e24b8da89ef6f474c0d5e719 [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.
8
9 - \<name\>, “[\<title\>](<link>)”, \<month\> \<year\>
10 - \<name\>, “[\<title\>](<link>)”, \<month\> \<year\>
11 - etc.
Dag Sverre Seljebotn3841f012018-08-28 21:07:53 +020012
13
14## Quick comments
15
Maxwell Corbin9144ad32018-08-28 12:58:11 -070016 - 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/
17
18 - 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 +090019
20 ```go
21 \\ list
22 package list[T]
23
24 type T interface{}
25
26 type List struct {
27 Val T
28 Next *List
29 }
30
31 // main
32 package main
33
34 import (
35 il "list"[int]
36 sl "list"[string]
37 )
38
39 var iList = il.List{3}
40 var sList = sl.List{"hello"}
41
42 // etc...
43 ```
44
45 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 -070046
Russell Johnston31d12712018-08-28 20:51:02 -070047 - 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.
48
Hajime Hoshif82716f2018-08-29 12:58:25 +090049 - 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.
50
Hajime Hoshi52978612018-08-29 13:01:29 +090051- 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?