2 min read
Successful type inference
Today we finish up the discussion on type inference. So we’ve now Type inference … If the two phases are successful, type inference determined a type argument for each bound type parameter: Pk ➞ Ak A type argument Ak may be a composite type, containing other bound type parameters Pk as element types (or even be just another bound type parameter). In a process of repeated simplification, the bound type parameters in each type argument are substituted with the respective type arguments for those type parameters until each type argument is free of bound type parameters.
2 min read
Precedence of type inference
Type inference … Type inference gives precedence to type information obtained from typed operands before considering untyped constants. Therefore, inference proceeds in two phases: The type equations are solved for the bound type parameters using type unification. If unification fails, type inference fails. Type unification comes up next in the spec, so we’ll learn exactly what that means soon. For each bound type parameter Pk for which no type argument has been inferred yet and for which one or more pairs (cj, Pk) with that same type parameter were collected, determine the constant kind of the constants cj in all those pairs the same way as for constant expressions.
2 min read
The many type equations
Type inference … Type inference supports calls of generic functions and assignments of generic functions to (explicitly function-typed) variables. So just to call out this point, made in passing: You cannot assign the result of a generic function to a generic, non-instantiated type, even if inferrence should be intuitive. Do demonstrate: type S[T ~int | ~float64] struct { Value T } func sum[V ~int | ~float32](a, b V) V { return a + b } // cannot use generic type S[T ~int | ~float64] without instantiation x := S{ Value: sum(int(1), int(2)), } Even though the type returned from sum() is obviously int, we cannot do this assignment.
2 min read
Bound type parameters
Type inference … Given a set of type equations, the type parameters to solve for are the type parameters of the functions that need to be instantiated and for which no explicit type arguments is provided. These type parameters are called bound type parameters. For instance, in the dedup example above, the type parameters P and E are bound to dedup. An argument to a generic function call may be a generic function itself.
17 min read
Error handling in Go web apps shouldn't be so awkward
A useful error handling pattern for Go REST, gRPC, and other services.
3 min read
Type equations
I don’t have a lot to expand on in this section, except to offer a pre-amble about some technical terms and symbols that won’t be familiar to everyone: ≡ is a symbol from mathematics that means “identical to”. It’s similar to = which we’re all famliar with, but “stricter”. The spec uses variants of this symbol in some following equations, so it’s nice to understand what the symbol means originally. ≡A means “are assignable to each other”, as in: X ≡A Y means “X is assignable to Y and Y is assignable to X” ≡C means “satisifes constraint”, as in: X ≡C ~int means “X satisfies constraint ~int”.
2 min read
Type inference
We just covered instantiations, and learned that it is often possible to infer generic types. Nowe we’ll examine how that mechanism works. This bit gets a bit into the weeds. You’ll be forgiven if you choose to skip over this. Type inference A use of a generic function may omit some or all type arguments if they can be inferred from the context within which the function is used, including the constraints of the function’s type parameters.
Subscribe to Boldly Go: Daily
Every day I'll send you advice to improve your understanding of Go. Don't miss out! I will respect your inbox, and honor my privacy policy.
Unsure? Browse the archive.
2 min read
Partial type argument lists
Instantiations … A partial type argument list cannot be empty; at least the first argument must be present. The list is a prefix of the full list of type arguments, leaving the remaining arguments to be inferred. Loosely speaking, type arguments may be omitted from “right to left”. func apply[S ~[]E, E any](s S, f func(E) E) S { … } f0 := apply[] // illegal: type argument list cannot be empty f1 := apply[[]int] // type argument for S explicitly provided, type argument for E inferred f2 := apply[[]string, string] // both type arguments explicitly provided var bytes []byte r := apply(bytes, func(byte) byte { … }) // both type arguments inferred from the function arguments Let’s demonstrate this by refering to the example from yesterday.
2 min read
When function instantiations can be inferred
A quick update on my livestream: It’s on hold until February, as my family and I made a bit of a last-minute trip to visit family for the month of January, so I won’t be in my studio for a while. Instantiations … When using a generic function, type arguments may be provided explicitly, or they may be partially or completely inferred from the context in which the function is used.
3 min read
Instantiations
Instantiations A generic function or type is instantiated by substituting type arguments for the type parameters. Instantiation proceeds in two steps: Each type argument is substituted for its corresponding type parameter in the generic declaration. This substitution happens across the entire function or type declaration, including the type parameter list itself and any types in that list. After substitution, each type argument must satisfy the constraint (instantiated, if necessary) of the corresponding type parameter.
2 min read
Passing slices to variadic functions
Passing arguments to ... parameters … If the final argument is assignable to a slice type []T and is followed by ..., it is passed unchanged as the value for a ...T parameter. In this case no new slice is created. Given the slice s and call s := []string{"James", "Jasmine"} Greeting("goodbye:", s...) within Greeting, who will have the same value as s with the same underlying array. This leads to a few gotchas that I’ll spend today talking about.