Source file src/internal/types/testdata/examples/functions.go

     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 "does not match" */ )
   154  	ffboth(send /* ERROR "does not match" */ )
   155  
   156  	ffrecv(both /* ERROR "does not match" */ )
   157  	ffrecv(recv)
   158  	ffrecv(send /* ERROR "does not match" */ )
   159  
   160  	ffsend(both /* ERROR "does not match" */ )
   161  	ffsend(recv /* ERROR "does not match" */ )
   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 intSlice []int
   178  	g1([]int{})
   179  	g1(intSlice{})
   180  	g2(nil, 0)
   181  
   182  	type myString string
   183  	var s1 string
   184  	g3(nil, "1", myString("2"), "3")
   185  	g3(& /* ERROR "cannot use &s1 (value of type *string) as *myString value in argument to g3" */ s1, "1", myString("2"), "3")
   186  	_ = s1
   187  
   188  	type myStruct struct{x int}
   189  	var s2 myStruct
   190  	g3(nil, struct{x int}{}, myStruct{})
   191  	g3(&s2, struct{x int}{}, myStruct{})
   192  	g3(nil, myStruct{}, struct{x int}{})
   193  	g3(&s2, myStruct{}, struct{x int}{})
   194  }
   195  
   196  // Here's a realistic example.
   197  
   198  func append[T any](s []T, t ...T) []T { panic(0) }
   199  
   200  func _() {
   201  	var f func()
   202  	type Funcs []func()
   203  	var funcs Funcs
   204  	_ = append(funcs, f)
   205  }
   206  
   207  // Generic type declarations cannot have empty type parameter lists
   208  // (that would indicate a slice type). Thus, generic functions cannot
   209  // have empty type parameter lists, either. This is a syntax error.
   210  
   211  func h[] /* ERROR "empty type parameter list" */ () {}
   212  
   213  func _() {
   214  	h /* ERROR "cannot index" */ [] /* ERROR "operand" */ ()
   215  }
   216  
   217  // Generic functions must have a function body.
   218  
   219  func _ /* ERROR "generic function is missing function body" */ [P any]()
   220  

View as plain text