
the-swift-rogramming-language
.pdf
return y
}
return x
}
Because Int and Double, for example, both conform to the Comparable protocol, this function accepts arguments of either type. In contrast with generic types, you don’t specify a generic argument clause when you use a generic function or initializer. The type arguments are instead inferred from the type of the arguments passed to the function or initializer.
simpleMin(17, 42) // T is inferred to be Int
simpleMin(3.14159, 2.71828) // T is inferred to be Double
Where Clauses
You can specify additional requirements on type parameters and their associated types by including a where clause after the generic parameter list. A where clause consists of the keyword where, followed by a comma-separated list of one or more requirements.
The requirements in a where clause specify that a type parameter inherits from a class or conforms to a protocol or protocol composition. Although the where clause provides syntactic sugar for expressing simple constraints on type parameters (for instance, T: Comparable is equivalent to T where T: Comparable and so on), you can use it to provide more complex constraints on type parameters and their associated types. For instance, you can express the constraints that a generic type T inherits from a class C and conforms to a
protocol P as <T where T: C, T: P>.
As mentioned above, you can constrain the associated types of type parameters to conform to protocols. For example, the generic parameter clause <T: Generator where T.Element: Equatable> specifies that T conforms to the Generator protocol and the associated type of T,
T.Element, conforms to the Equatable protocol (T has the associated type Element because
Generator declares Element and T conforms to Generator).
You can also specify the requirement that two types be identical, using the
For example, the generic parameter clause <T: Generator, U: Generator where T.Element ==
U.Element> expresses the constraints that T and U conform to the Generator protocol and that their associated types must be identical.
Any type argument substituted for a type parameter must meet all the constraints and requirements placed on the type parameter.

You can overload a generic function or initializer by providing different constraints, requirements, or both on the type parameters in the generic parameter clause. When you call an overloaded generic function or initializer, the compiler uses these constraints to resolve which overloaded function or initializer to invoke.
You can subclass a generic class, but the subclass must also be a generic class.
G R A M M A R O F A G E N E R I C P A R A M E T E R C L A U S E
generic-parameter-clause → < generic-parameter-list requirement-clause opt > generic-parameter-list → generic-parameter generic-parameter , generic-parameter-
list
generic-parameter → type-name generic-parameter → type-name : type-identifier
generic-parameter → type-name : protocol-composition-type
requirement-clause → where requirement-list
requirement-list → requirement requirement , requirement-list requirement → conformance-requirement same-type-requirement
conformance-requirement → type-identifier : type-identifier conformance-requirement → type-identifier : protocol-composition-type same-type-requirement → type-identifier == type-identifier
Generic Argument Clause
A generic argument clause specifies the type arguments of a generic type. A generic argument clause is enclosed in angle brackets (<>) and has the following form:
< generic argument list >
The generic argument list is a comma-separated list of type arguments. A type argument is the name of an actual concrete type that replaces a corresponding type parameter in the generic parameter clause of a generic type. The result is a specialized version of that generic type. As an example, the Swift standard library defines a generic dictionary type as:
struct Dictionary<KeyType: Hashable, ValueType>: Collection, DictionaryLiteralConvertible {
/* ... */
}

The specialized version of the generic Dictionary type, Dictionary<String, Int> is formed by replacing the generic parameters KeyType: Hashable and ValueType with the concrete type arguments String and Int. Each type argument must satisfy all the constraints of the generic parameter it replaces, including any additional requirements specified in a where clause. In the example above, the KeyType type parameter is constrained to conform to the Hashable protocol and therefore String must also conform to the Hashable protocol.
You can also replace a type parameter with a type argument that is itself a specialized version of a generic type (provided it satisfies the appropriate constraints and requirements). For example, you can replace the type parameter T in Array<T> with a specialized version of an array, Array<Int>, to form an array whose elements are themselves arrays of integers.
let arrayOfArrays: Array<Array<Int>> = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
As mentioned in Generic Parameter Clause, you don’t use a generic argument clause to specify the type arguments of a generic function or initializer.
G R A M M A R O F A G E N E R I C A R G U M E N T C L A U S E
generic-argument-clause → < generic-argument-list >
generic-argument-list → generic-argument generic-argument , generic-argument-list generic-argument → type

Summary of the Grammar
Statements
G R A M M A R O F A S T A T E M E N T
statement → expression ;opt statement → declaration ;opt statement → loop-statement ;opt statement → branch-statement ;opt statement → labeled-statement
statement → control-transfer-statement ;opt statements → statement statements opt
G R A M M A R O F A L O O P S T A T E M E N T
loop-statement → for-statement loop-statement → for-in-statement loop-statement → while-statement loop-statement → do-while-statement
G R A M M A R O F A F O R S T A T E M E N T
for-statement |
→ for |
for-init opt ; |
expressionopt ; expressionopt code-block |
for-statement |
→ for |
( for-init opt |
; expressionopt ; expressionopt ) code-block |
for-init → variable-declaration |
expression-list |
G R A M M A R O F A F O R- I N S T A T E M E N T
for-in-statement → for pattern in expression code-block
G R A M M A R O F A W H I L E S T A T E M E N T
while-statement → while while-condition code-block while-condition → expression declaration
G R A M M A R O F A D O - W H I L E S T A T E M E N T
do-while-statement → do code-block while while-condition

G R A M M A R O F A B R A N C H S T A T E M E N T
branch-statement → if-statement branch-statement → switch-statement
G R A M M A R O F A N I F S T A T E M E N T
if-statement |
→ if if-condition code-block else-clause opt |
if-condition |
→ expression declaration |
else-clause |
→ else code-block else if-statement |
G R A M M A R O F A S W I T C H S T A T E M E N T
switch-statement → switch expression { switch-cases opt } switch-cases → switch-case switch-cases opt
switch-case → case-label statements default-label statements switch-case → case-label ; default-label ;
case-label → case case-item-list :
case-item-list → pattern guard-clause opt pattern guard-clause opt , case-item-list default-label → default :
guard-clause → where guard-expression guard-expression → expression
G R A M M A R O F A L A B E L E D S T A T E M E N T
labeled-statement → statement-label loop-statement statement-label switchstatement
statement-label → label-name : label-name → identifier
G R A M M A R O F A C O N T R O L T R A N S F E R S T A T E M E N T
control-transfer-statement → break-statement control-transfer-statement → continue-statement control-transfer-statement → fallthrough-statement control-transfer-statement → return-statement
G R A M M A R O F A B R E A K S T A T E M E N T
break-statement → break label-name opt
G R A M M A R O F A C O N T I N U E S T A T E M E N T
continue-statement → continue label-name opt

G R A M M A R O F A FA L LT H R O U G H S T A T E M E N T
fallthrough-statement → fallthrough
G R A M M A R O F A R E T U R N S T A T E M E N T
return-statement → return expressionopt
Generic Parameters and Arguments
G R A M M A R O F A G E N E R I C P A R A M E T E R C L A U S E
generic-parameter-clause → < generic-parameter-list requirement-clause opt > generic-parameter-list → generic-parameter generic-parameter , generic-parameter-
list
generic-parameter → type-name generic-parameter → type-name : type-identifier
generic-parameter → type-name : protocol-composition-type
requirement-clause → where requirement-list
requirement-list → requirement requirement , requirement-list requirement → conformance-requirement same-type-requirement
conformance-requirement → type-identifier : type-identifier conformance-requirement → type-identifier : protocol-composition-type same-type-requirement → type-identifier == type-identifier
G R A M M A R O F A G E N E R I C A R G U M E N T C L A U S E
generic-argument-clause → < generic-argument-list >
generic-argument-list → generic-argument generic-argument , generic-argument-list generic-argument → type
Declarations
G R A M M A R O F A D E C L A R A T I O N
declaration → import-declaration declaration → constant-declaration declaration → variable-declaration declaration → typealias-declaration

declaration → function-declaration declaration → enum-declaration declaration → struct-declaration declaration → class-declaration declaration → protocol-declaration declaration → initializer-declaration declaration → deinitializer-declaration declaration → extension-declaration declaration → subscript-declaration declaration → operator-declaration declarations → declaration declarations opt
declaration-specifiers → declaration-specifier declaration-specifiers opt
declaration-specifier → class mutating nonmutating override static unowned
unowned(safe) unowned(unsafe) weak
G R A M M A R O F A T O P - L E V E L D E C L A R A T I O N
top-level-declaration → statements opt
G R A M M A R O F A C O D E B L O C K
code-block → { statements opt }
G R A M M A R O F A N I M P O R T D E C L A R A T I O N
import-declaration → attributes opt import import-kindopt import-path
import-kind → typealias struct class enum protocol var func
import-path → import-path-identifier import-path-identifier . import-path import-path-identifier → identifier operator
G R A M M A R O F A C O N S T A N T D E C L A R A T I O N
constant-declaration → attributes opt declaration-specifiers opt let pattern-initializer-list
pattern-initializer-list → pattern-initializer pattern-initializer , pattern-initializer-list pattern-initializer → pattern initializeropt
initializer → = expression
G R A M M A R O F A V A R I A B L E D E C L A R A T I O N
variable-declaration → variable-declaration-head pattern-initializer-list variable-declaration → variable-declaration-head variable-name type-
annotation code-block

variable-declaration → variable-declaration-head variable-name typeannotation getter-setter-block
variable-declaration → variable-declaration-head variable-name typeannotation getter-setter-keyword-block
variable-declaration → variable-declaration-head variable-name typeannotation initializeropt willSet-didSet-block
variable-declaration-head → attributes opt declaration-specifiers opt var variable-name → identifier
getter-setter-block → { getter-clause setter-clause opt } getter-setter-block → { setter-clause getter-clause } getter-clause → attributes opt get code-block
setter-clause → attributes opt set setter-name opt code-block setter-name → ( identifier )
getter-setter-keyword-block → { getter-keyword-clause setter-keyword-clause opt } getter-setter-keyword-block → { setter-keyword-clause getter-keyword-clause } getter-keyword-clause → attributes opt get
setter-keyword-clause → attributes opt set
willSet-didSet-block → { willSet-clause didSet-clause opt } willSet-didSet-block → { didSet-clause willSet-clause } willSet-clause → attributes opt willSet setter-name opt code-block didSet-clause → attributes opt didSet setter-name opt code-block
G R A M M A R O F A T Y P E A L I A S D E C L A R A T I O N
typealias-declaration → typealias-head typealias-assignment typealias-head → typealias typealias-name
typealias-name → identifier typealias-assignment → = type
G R A M M A R O F A F U N C T I O N D E C L A R A T I O N
function-declaration → function-head function-name generic-parameter- clause opt function-signature function-body
function-head → attributes opt declaration-specifiers opt func function-name → identifier operator
function-signature → parameter-clauses function-result opt function-result → -> attributes opt type

function-body → code-block
parameter-clauses → parameter-clause parameter-clauses opt parameter-clause → ( ) ( parameter-list ... opt ) parameter-list → parameter parameter , parameter-list
parameter → inout opt let opt # opt parameter-name local-parameter-name opt typeannotation default-argument-clause opt
parameter → inout opt var # opt parameter-name local-parameter-name opt typeannotation default-argument-clause opt
parameter → attributes opt type parameter-name → identifier _ local-parameter-name → identifier _ default-argument-clause → = expression
G R A M M A R O F A N E N U M E R A T I O N D E C L A R A T I O N
enum-declaration → attributes opt union-style-enum attributes opt raw-value-style- enum
union-style-enum → enum-name generic-parameter-clause opt { union-style-enum-
members opt }
union-style-enum-members → union-style-enum-member union-style-enum- members opt
union-style-enum-member → declaration union-style-enum-case-clause union-style-enum-case-clause → attributes opt case union-style-enum-case-list union-style-enum-case-list → union-style-enum-case union-style-enum-case , union-
style-enum-case-list
union-style-enum-case → enum-case-name tuple-type opt enum-name → identifier
enum-case-name → identifier
raw-value-style-enum → enum-name generic-parameter-clause opt : typeidentifier { raw-value-style-enum-members opt }
raw-value-style-enum-members → raw-value-style-enum-member raw-value-style- enum-members opt
raw-value-style-enum-member → declaration raw-value-style-enum-case-clause raw-value-style-enum-case-clause → attributes opt case raw-value-style-enum-case-
list
raw-value-style-enum-case-list → raw-value-style-enum-case raw-value-style-enum- case , raw-value-style-enum-case-list

raw-value-style-enum-case → enum-case-name raw-value-assignment opt raw-value-assignment → = literal
G R A M M A R O F A S T R U C T U R E D E C L A R A T I O N
struct-declaration → attributes opt struct struct-name generic-parameter- clause opt type-inheritance-clause opt struct-body
struct-name → identifier struct-body → { declarations opt }
G R A M M A R O F A C L A S S D E C L A R A T I O N
class-declaration → attributes opt class class-name generic-parameter-clause opt type- inheritance-clause opt class-body
class-name → identifier class-body → { declarations opt }
G R A M M A R O F A P R O T O C O L D E C L A R A T I O N
protocol-declaration → attributes opt protocol protocol-name type-inheritance- clause opt protocol-body
protocol-name → identifier
protocol-body → { protocol-member-declarations opt }
protocol-member-declaration → protocol-property-declaration protocol-member-declaration → protocol-method-declaration protocol-member-declaration → protocol-initializer-declaration protocol-member-declaration → protocol-subscript-declaration protocol-member-declaration → protocol-associated-type-declaration protocol-member-declarations → protocol-member-declaration protocol-member-
declarations opt
G R A M M A R O F A P R O T O C O L P R O P E R T Y D E C L A R A T I O N
protocol-property-declaration → variable-declaration-head variable-name typeannotation getter-setter-keyword-block
G R A M M A R O F A P R O T O C O L M E T H O D D E C L A R A T I O N
protocol-method-declaration → function-head function-name generic-parameter- clause opt function-signature
G R A M M A R O F A P R O T O C O L I N I T I A L I Z E R D E C L A R A T I O N