blob: db8bae0a46d3d633d1d79511c5deebf11c25f9e6 [file] [log] [blame] [view]
Ian Lance Taylorb571c322016-03-31 09:36:41 +11001# Proposal: Go should have generics
2
3Author: [Ian Lance Taylor](iant@golang.org)
4
5Created: January 2011
6
7Last updated: April 2016
8
9Discussion at https://golang.org/issue/15292
10
11## Abstract
12
13Go should support some form of generic programming.
14Generic programming enables the representation of algorithms and data
15structures in a generic form, with concrete elements of the code
16(such as types) factored out.
17It means the ability to express algorithms with minimal assumptions
18about data structures, and vice-versa
Suriyaa Sundararuban2c6bc832018-06-12 12:48:52 +000019(paraphrasing [Jazayeri, et al](https://www.dagstuhl.de/en/program/calendar/semhp/?semnr=98171)).
Ian Lance Taylorb571c322016-03-31 09:36:41 +110020
21## Background
22
23### Generic arguments in favor of generics
24
25People can write code once, saving coding time.
26People can fix a bug in one instance without having to remember to fix it
27in others.
28Generics avoid boilerplate: less coding by copying and editing.
29
30Generics save time testing code: they increase the amount of code
31that can be type checked at compile time rather than at run time.
32
33Every statically typed language in current use has generics in one
34form or another (even C has generics, where they are called preprocessor macros;
35[example](https://gcc.gnu.org/viewcvs/gcc/trunk/gcc/vec.h?revision=165314&view=markup&pathrev=165314)).
36
37### Existing support for generic programming in Go
38
39Go already supports a form of generic programming via interfaces.
40People can write an abstract algorithm that works with any type that
41implements the interface.
42However, interfaces are limited because the methods must use specific types.
43There is no way to write an interface with a method that takes an
44argument of type T, for any T, and returns a value of the same type.
45There is no way to write an interface with a method that compares two
46values of the same type T, for any T.
47The assumptions that interfaces require about the types that satisfy
48them are not minimal.
49
50Interfaces are not simply types; they are also values.
51There is no way to use interface types without using interface values,
52and interface values arent always efficient.
53There is no way to create a slice of the dynamic type of an interface.
54That is, there is no way to avoid boxing.
55
56### Specific arguments in favor of generics in Go
57
58Generics permit type-safe polymorphic containers.
59Go currently has a very limited set of such containers: slices, and
60maps of most but not all types.
61Not every program can be written using a slice or map.
62
63Look at the functions `SortInts`, `SortFloats`, `SortStrings` in the
64sort package.
65Or `SearchInts`, `SearchFloats`, `SearchStrings`.
66Or the `Len`, `Less`, and `Swap` methods of `byName` in package io/ioutil.
67Pure boilerplate copying.
68
69The `copy` and `append` functions exist because they make slices much
70more useful.
71Generics would mean that these functions are unnecessary.
72Generics would make it possible to write similar functions for maps
73and channels, not to mention user created data types.
74Granted, slices are the most important composite data type, and thats why
75these functions were needed, but other data types are still useful.
76
77It would be nice to be able to make a copy of a map.
78Right now that function can only be written for a specific map type,
79but, except for types, the same code works for any map type.
80Similarly, it would be nice to be able to multiplex one channel onto
81two, without having to rewrite the function for each channel type.
82One can imagine a range of simple channel manipulators, but they can
83not be written because the type of the channel must be specified
84explicitly.
85
86Generics let people express the relationship between function parameters
87and results.
88Consider the simple Transform function that calls a function on every
89element of a slice, returning a new slice.
90We want to write something like
91```
92func Transform(s []T, f func(T) U) []U
93```
94but this can not be expressed in current Go.
95
96In many Go programs, people only have to write explicit types in function
97signatures.
98Without generics, they also have to write them in another place: in the
99type assertion needed to convert from an interface type back to the
100real type.
101The lack of static type checking provided by generics makes the code
102heavier.
103
104### What we want from generics in Go
105
106Any implementation of generics in Go should support the following.
107
108* Define generic types based on types that are not known until they are instantiated.
109* Write algorithms to operate on values of these types.
110* Name generic types and name specific instantiations of generic types.
111* Use types derived from generic types, as in making a slice of a generic type,
112 or conversely, given a generic type known to be a slice, defining a variable
113 with the slices element type.
114* Restrict the set of types that may be used to instantiate a generic type, to
115 ensure that the generic type is only instantiated with types that support the
Andrew Gerrandab418bc2016-04-14 13:38:40 +1000116 required operations.
Ian Lance Taylorb571c322016-03-31 09:36:41 +1100117* Do not require an explicit relationship between the definition of a generic
118 type or function and its use. That is, programs should not have to
119 explicitly say *type T implements generic G*.
120* Write interfaces that describe explicit relationships between generic types,
121 as in a method that takes two parameters that must both be the same unknown type.
122* Do not require explicit instantiation of generic types or functions; they
123 should be instantiated as needed.
124
125### The downsides of generics
126
127Generics affect the whole language.
128It is necessary to evaluate every single language construct to see how
129it will work with generics.
130
131Generics affect the whole standard library.
132It is desirable to have the standard library make effective use of generics.
133Every existing package should be reconsidered to see whether it would benefit
134from using generics.
135
136It becomes tempting to build generics into the standard library at a
137very low level, as in C++ `std::basic_string<char, std::char_traits<char>, std::allocator<char> >`.
138This has its benefits&mdash;otherwise nobody would do it&mdash;but it has
139wide-ranging and sometimes surprising effects, as in incomprehensible
140C++ error messages.
141
Suriyaa Sundararuban2c6bc832018-06-12 12:48:52 +0000142As [Russ pointed out](https://research.swtch.com/generic), generics are
Ian Lance Taylorb571c322016-03-31 09:36:41 +1100143a trade off between programmer time, compilation time, and execution
144time.
145
146Go is currently optimizing compilation time and execution time at the
147expense of programmer time.
148Compilation time is a significant benefit of Go.
149Can we retain compilation time benefits without sacrificing too much
150execution time?
151
152Unless we choose to optimize execution time, operations that appear
153cheap may be more expensive if they use values of generic type.
154This may be subtly confusing for programmers.
155I think this is less important for Go than for some other languages,
156as some operations in Go already have hidden costs such as array
157bounds checks.
158Still, it would be essential to ensure that the extra cost of using
159values of generic type is tightly bounded.
160
161Go has a lightweight type system.
162Adding generic types inevitably makes the type system more complex.
163It is essential that the result remain lightweight.
164
165The upsides of the downsides are that Go is a relatively small
166language, and it really is possible to consider every aspect of the
167language when adding generics.
168At least the following sections of the spec would need to be extended:
169Types, Type Identity, Assignability, Type assertions, Calls, Type
170switches, For statements with range clauses.
171
172Only a relatively small number of packages will need to be
173reconsidered in light of generics: container/*, sort, flag, perhaps
174bytes.
175Packages that currently work in terms of interfaces will generally be
176able to continue doing so.
177
178### Conclusion
179
180Generics will make the language safer, more efficient to use, and more
181powerful.
182These advantages are harder to quantify than the disadvantages, but
183they are real.
184
185## Examples of potential uses of generics in Go
186
187* Containers
188 * User-written hash tables that are compile-time type-safe, rather than
189 converting slice keys to string and using maps
190 * Sorted maps (red-black tree or similar)
191 * Double-ended queues, circular buffers
192 * A simpler Heap
193 * `Keys(map[K]V) []K`, `Values(map[K]V) []V`
194 * Caches
195 * Compile-time type-safe `sync.Pool`
196* Generic algorithms that work with these containers in a type-safe way.
197 * Union/Intersection
198 * Sort, StableSort, Find
199 * Copy (a generic container, and also copy a map)
200 * Transform a container by applying a function--LISP `mapcar` and friends
201* math and math/cmplx
202* testing/quick.{`Check`,`CheckEqual`}
203* Mixins
204 * like `ioutil.NopCloser`, but preserving other methods instead of
205 restricting to the passed-in interface (see the `ReadFoo` variants of
206 `bytes.Buffer`)
207* protobuf `proto.Clone`
208* Eliminate boilerplate when calling sort function
209* Generic diff: `func [T] Diff(x, y []T) []range`
210* Channel operations
211 * Merge N channels onto one
212 * Multiplex one channel onto N
Suriyaa Sundararuban2c6bc832018-06-12 12:48:52 +0000213 * The [worker-pool pattern](https://play.golang.org/p/b5XRHnxzZF)
Ian Lance Taylorb571c322016-03-31 09:36:41 +1100214* Graph algorithms, for example immediate dominator computation
215* Multi-dimensional arrays (not slices) of different lengths
216* Many of the packages in go.text could benefit from it to avoid duplicate
217 implementation or APIs for `string` and `[]byte` variants; many points that
218 could benefit need high performance, though, and generics should provide that
219 benefit
220
221## Proposal
222
223I won’t discuss a specific implementation proposal here: my hope is
224that this document helps show people that generics are worth having
225provided the downsides can be kept under control.
226
227The following documents are my previous generics proposals,
228presented for historic reference. All are flawed in various ways.
229
Andrew Gerrandbb8acc22016-04-14 13:38:40 +1000230* [Type functions](15292/2010-06-type-functions.md) (June 2010)
231* [Generalized types](15292/2011-03-gen.md) (March 2011)
232* [Generalized types](15292/2013-10-gen.md) (October 2013)
233* [Type parameters](15292/2013-12-type-params.md) (December 2013)