1 // Copyright 2019 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 // This file shows some examples of type-parameterized functions.
6
7 package p
8
9 // Reverse is a generic function that takes a []T argument and
10 // reverses that slice in place.
11 func Reverse[T any](list []T) {
12 i := 0
13 j := len(list)-1
14 for i < j {
15 list[i], list[j] = list[j], list[i]
16 i++
17 j--
18 }
19 }
20
21 func _() {
22 // Reverse can be called with an explicit type argument.
23 Reverse[int](nil)
24 Reverse[string]([]string{"foo", "bar"})
25 Reverse[struct{x, y int}]([]struct{x, y int}{{1, 2}, {2, 3}, {3, 4}})
26
27 // Since the type parameter is used for an incoming argument,
28 // it can be inferred from the provided argument's type.
29 Reverse([]string{"foo", "bar"})
30 Reverse([]struct{x, y int}{{1, 2}, {2, 3}, {3, 4}})
31
32 // But the incoming argument must have a type, even if it's a
33 // default type. An untyped nil won't work.
34 // Reverse(nil) // this won't type-check
35
36 // A typed nil will work, though.
37 Reverse([]int(nil))
38 }
39
40 // Certain functions, such as the built-in `new` could be written using
41 // type parameters.
42 func new[T any]() *T {
43 var x T
44 return &x
45 }
46
47 // When calling our own `new`, we need to pass the type parameter
48 // explicitly since there is no (value) argument from which the
49 // result type could be inferred. We don't try to infer the
50 // result type from the assignment to keep things simple and
51 // easy to understand.
52 var _ = new[int]()
53 var _ *float64 = new[float64]() // the result type is indeed *float64
54
55 // A function may have multiple type parameters, of course.
56 func foo[A, B, C any](a A, b []B, c *C) B {
57 // do something here
58 return b[0]
59 }
60
61 // As before, we can pass type parameters explicitly.
62 var s = foo[int, string, float64](1, []string{"first"}, new[float64]())
63
64 // Or we can use type inference.
65 var _ float64 = foo(42, []float64{1.0}, &s)
66
67 // Type inference works in a straight-forward manner even
68 // for variadic functions.
69 func variadic[A, B any](A, B, ...B) int { panic(0) }
70
71 // var _ = variadic(1) // ERROR not enough arguments
72 var _ = variadic(1, 2.3)
73 var _ = variadic(1, 2.3, 3.4, 4.5)
74 var _ = variadic[int, float64](1, 2.3, 3.4, 4)
75
76 // Type inference also works in recursive function calls where
77 // the inferred type is the type parameter of the caller.
78 func f1[T any](x T) {
79 f1(x)
80 }
81
82 func f2a[T any](x, y T) {
83 f2a(x, y)
84 }
85
86 func f2b[T any](x, y T) {
87 f2b(y, x)
88 }
89
90 func g2a[P, Q any](x P, y Q) {
91 g2a(x, y)
92 }
93
94 func g2b[P, Q any](x P, y Q) {
95 g2b(y, x)
96 }
97
98 // Here's an example of a recursive function call with variadic
99 // arguments and type inference inferring the type parameter of
100 // the caller (i.e., itself).
101 func max[T interface{ ~int }](x ...T) T {
102 var x0 T
103 if len(x) > 0 {
104 x0 = x[0]
105 }
106 if len(x) > 1 {
107 x1 := max(x[1:]...)
108 if x1 > x0 {
109 return x1
110 }
111 }
112 return x0
113 }
114
115 // When inferring channel types, the channel direction is ignored
116 // for the purpose of type inference. Once the type has been in-
117 // fered, the usual parameter passing rules are applied.
118 // Thus even if a type can be inferred successfully, the function
119 // call may not be valid.
120
121 func fboth[T any](chan T) {}
122 func frecv[T any](<-chan T) {}
123 func fsend[T any](chan<- T) {}
124
125 func _() {
126 var both chan int
127 var recv <-chan int
128 var send chan<-int
129
130 fboth(both)
131 fboth(recv /* ERROR cannot use */ )
132 fboth(send /* ERROR cannot use */ )
133
134 frecv(both)
135 frecv(recv)
136 frecv(send /* ERROR cannot use */ )
137
138 fsend(both)
139 fsend(recv /* ERROR cannot use */)
140 fsend(send)
141 }
142
143 func ffboth[T any](func(chan T)) {}
144 func ffrecv[T any](func(<-chan T)) {}
145 func ffsend[T any](func(chan<- T)) {}
146
147 func _() {
148 var both func(chan int)
149 var recv func(<-chan int)
150 var send func(chan<- int)
151
152 ffboth(both)
153 ffboth(recv /* ERROR cannot use */ )
154 ffboth(send /* ERROR cannot use */ )
155
156 ffrecv(both /* ERROR cannot use */ )
157 ffrecv(recv)
158 ffrecv(send /* ERROR cannot use */ )
159
160 ffsend(both /* ERROR cannot use */ )
161 ffsend(recv /* ERROR cannot use */ )
162 ffsend(send)
163 }
164
165 // When inferring elements of unnamed composite parameter types,
166 // if the arguments are defined types, use their underlying types.
167 // Even though the matching types are not exactly structurally the
168 // same (one is a type literal, the other a named type), because
169 // assignment is permitted, parameter passing is permitted as well,
170 // so type inference should be able to handle these cases well.
171
172 func g1[T any]([]T) {}
173 func g2[T any]([]T, T) {}
174 func g3[T any](*T, ...T) {}
175
176 func _() {
177 type intSlize []int
178 g1([]int{})
179 g1(intSlize{})
180 g2(nil, 0)
181
182 type myString string
183 var s1 string
184 g3(nil, "1", myString("2"), "3")
185 g3(&s1, "1", myString /* ERROR does not match */ ("2"), "3")
186
187 type myStruct struct{x int}
188 var s2 myStruct
189 g3(nil, struct{x int}{}, myStruct{})
190 g3(&s2, struct{x int}{}, myStruct{})
191 g3(nil, myStruct{}, struct{x int}{})
192 g3(&s2, myStruct{}, struct{x int}{})
193 }
194
195 // Here's a realistic example.
196
197 func append[T any](s []T, t ...T) []T { panic(0) }
198
199 func _() {
200 var f func()
201 type Funcs []func()
202 var funcs Funcs
203 _ = append(funcs, f)
204 }
205
206 // Generic type declarations cannot have empty type parameter lists
207 // (that would indicate a slice type). Thus, generic functions cannot
208 // have empty type parameter lists, either. This is a syntax error.
209
210 func h[] /* ERROR empty type parameter list */ () {}
211
212 func _() {
213 h /* ERROR cannot index */ [] /* ERROR operand */ ()
214 }
215
216 // Parameterized functions must have a function body.
217
218 func _ /* ERROR missing function body */ [P any]()
219
View as plain text