Subscripts
A subscript is a reusable piece of code that yields the value of an object, or part thereof. It operates very similarly to a function, but rather than returning a value to its caller, it temporarily yields control for the caller to access the yielded value.
The program above declares a subscript named min
that accepts two integers and yields the value of the smallest. A subscript is called using its name followed by its arguments, enclosed in square brackets (unlike functions, which require parentheses). Here, it is called in main
to print the minimum of 1
and 2
.
Note that, because min
does not return a value, its parameters need not to be passed with the sink
convention. Indeed, they do not escape from the subscript.
To better understand, let us instrument the subscript to observe its behavior. Similarly to functions, note that if the body of a subscript involves multiple statements, yielded values must be indicated by a yield
statement. Further, a subscript must have exactly one yield
statement on every possible execution path.
In the program above, min
has been changed so that it prints a message before and after yielding a value. In main
, the first message appears after min
is called when the projection starts; the second message appears when the projection ends.
Member subscripts
Subscripts declared in type declarations and extensions are called member subscripts. Just like methods, they receive an implicit receiver parameter.
A member subscript can be anonymous. In that case, it is called by affixing square brackets directly after the receiver.
Subscript bundles
Just like methods, subscripts and member subscripts can bundle multiple implementations to represent different variant of the same functionality depending on the context in which the subscript is being used.
inout
subscripts
inout
subscriptsAn inout
subscript projects values mutably:
A mutable subscript can always be used immutably as well. However, in the example above, because the parameters are inout
, arguments to min_inout
will have to be passed inout
even when the subscript is used immutably.
To solve that problem, we can mark the parameters yielded
instead, which act as a placeholder for either let
, inout
, or sink
depending on the way the subscript is being used.
Here, the immutable variant of the subscript is synthesized from the mutable one. In some cases, however, you may need to implement different behavior. In such situations, you can bundle multiple implementations together:
set
subscripts
set
subscriptsA set
subscript does not project any value. Instead, it is used when the value produced by a subscript need not be used, but only assigned to a new value.
A set
subscript accepts an implicit sink
parameter named new_value
denoting the value to assign:
In the program above, the value of the subscript is not required to perform the assigment. So rather than applying the inout
variant, the compiler will choose to apply the set
variant.
sink
subscripts
sink
subscriptsA sink
subscript returns a value instead of projecting one, consuming its yielded
parameters. It is used when a call to a subscript is the last use of its yielded
arguments, or when the result of the subscript is being consumed.
Note: If the body of a sink
subscript variant involves multiple statements, returned values must be indicated by a return
statement rather than a yield
statement.
The sink
variant of a subscript can always be synthesized from the let
variant.
Computed properties
A member subscript that accepts no arguments can be declared as a computed property, which is accessed without square brackets.
Last updated