Generic functions as operands

September 12, 2023

Operands

An operand name denoting a generic function may be followed by a list of type arguments; the resulting operand is an instantiated function.

So first off, recall that an operand may be a function literal:

var x = func() { /* ... */ }

Or a variable that represents a function:

var F = func() { /* ... */ }
var f = F // <--- `F` is a variable that represents a function

Or another expression that evaluates to a function:

func X() func() { // X() returns a function
	return func() { /* ... */ }
}

var x = X() // `x` now represents the function returned by X()

The above sentence expands on this simple concept, to allow the instantiation of generic functions. This is required because a function variable or operand cannot be generic. It must be instantiated.

func First[A int | uint](args ...A) A {
	return args[0]
}

var f = First // cannot use generic function First without instantiation

var g = First[int] // Valid, g is of type func(...int) int

Quotes from The Go Programming Language Specification Version of August 2, 2023


Share this

Direct to your inbox, daily. I respect your privacy .

Unsure? Browse the archive .

Related Content


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.


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.


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.

Get daily content like this in your inbox!

Subscribe