Initial commit
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
# About the Language Reference
|
||||
|
||||
Read the notation that the formal grammar uses.
|
||||
|
||||
This part of the book describes the formal grammar of the Swift programming language.
|
||||
The grammar described here is intended to help you understand the language in more
|
||||
detail, rather than to allow you to directly implement a parser or compiler.
|
||||
|
||||
The Swift language is relatively small, because many common types, functions, and operators
|
||||
that appear virtually everywhere in Swift code
|
||||
are actually defined in the Swift standard library. Although these types, functions,
|
||||
and operators aren't part of the Swift language itself,
|
||||
they're used extensively in the discussions and code examples in this part of the book.
|
||||
|
||||
## How to Read the Grammar
|
||||
|
||||
The notation used to describe the formal grammar of the Swift programming language
|
||||
follows a few conventions:
|
||||
|
||||
- An arrow (→) is used to mark grammar productions and can be read as "can consist of."
|
||||
- Syntactic categories are indicated by *italic* text and appear on both sides
|
||||
of a grammar production rule.
|
||||
- Literal words and punctuation are indicated by **`boldface constant width`** text
|
||||
and appear only on the right-hand side of a grammar production rule.
|
||||
- Alternative grammar productions are separated by vertical
|
||||
bars (|). When alternative productions are too long to read easily,
|
||||
they're broken into multiple grammar production rules on new lines.
|
||||
- In a few cases, regular font text is used to describe the right-hand side
|
||||
of a grammar production rule.
|
||||
- Optional syntactic categories and literals are marked by a trailing
|
||||
question mark, *?*.
|
||||
|
||||
As an example, the grammar of a getter-setter block is defined as follows:
|
||||
|
||||
> Grammar of a getter-setter block:
|
||||
>
|
||||
> *getter-setter-block* → **`{`** *getter-clause* *setter-clause*_?_ **`}`** | **`{`** *setter-clause* *getter-clause* **`}`**
|
||||
|
||||
This definition indicates that a getter-setter block can consist of a getter clause
|
||||
followed by an optional setter clause, enclosed in braces,
|
||||
*or* a setter clause followed by a getter clause, enclosed in braces.
|
||||
The grammar production above is equivalent to the following two productions,
|
||||
where the alternatives are spelled out explicitly:
|
||||
|
||||
> Grammar of a getter-setter block:
|
||||
>
|
||||
>
|
||||
> *getter-setter-block* → **`{`** *getter-clause* *setter-clause*_?_ **`}`** \
|
||||
> *getter-setter-block* → **`{`** *setter-clause* *getter-clause* **`}`**
|
||||
|
||||
<!--
|
||||
This source file is part of the Swift.org open source project
|
||||
|
||||
Copyright (c) 2014 - 2022 Apple Inc. and the Swift project authors
|
||||
Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
|
||||
See https://swift.org/LICENSE.txt for license information
|
||||
See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
-->
|
||||
2746
skills/programming-swift/ReferenceManual/Attributes.md
Normal file
2746
skills/programming-swift/ReferenceManual/Attributes.md
Normal file
File diff suppressed because it is too large
Load Diff
3995
skills/programming-swift/ReferenceManual/Declarations.md
Normal file
3995
skills/programming-swift/ReferenceManual/Declarations.md
Normal file
File diff suppressed because it is too large
Load Diff
3287
skills/programming-swift/ReferenceManual/Expressions.md
Normal file
3287
skills/programming-swift/ReferenceManual/Expressions.md
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,372 @@
|
||||
# Generic Parameters and Arguments
|
||||
|
||||
Generalize declarations to abstract away concrete types.
|
||||
|
||||
This chapter describes parameters and arguments for generic types, functions, and
|
||||
initializers. When you declare a generic type, function, subscript, or initializer,
|
||||
you specify the type parameters that the generic type, function, or initializer
|
||||
can work with. These type parameters act as placeholders that
|
||||
are replaced by actual concrete type arguments when an instance of a generic type is
|
||||
created or a generic function or initializer is called.
|
||||
|
||||
For an overview of generics in Swift, see <doc:Generics>.
|
||||
|
||||
<!--
|
||||
NOTE: Generic types are sometimes referred to as :newTerm:`parameterized types`
|
||||
because they're declared with one or more type parameters.
|
||||
-->
|
||||
|
||||
## Generic Parameter Clause
|
||||
|
||||
A *generic parameter clause* specifies the type parameters of a generic
|
||||
type or function, along with any associated constraints and requirements on those parameters.
|
||||
A generic parameter clause is enclosed in angle brackets (<>)
|
||||
and has the following form:
|
||||
|
||||
```swift
|
||||
<<#generic parameter list#>>
|
||||
```
|
||||
|
||||
The *generic parameter list* is a comma-separated list of generic parameters,
|
||||
each of which has the following form:
|
||||
|
||||
```swift
|
||||
<#type parameter#>: <#constraint#>
|
||||
```
|
||||
|
||||
A generic parameter consists of a *type parameter* followed by
|
||||
an optional *constraint*. A *type parameter* is simply the name
|
||||
of a placeholder type
|
||||
(for example, `T`, `U`, `V`, `Key`, `Value`, and so on).
|
||||
You have access to the type parameters (and any of their associated types) in the rest of the
|
||||
type, function, or initializer declaration, including in the signature of the function
|
||||
or initializer.
|
||||
|
||||
The *constraint* specifies that a type parameter inherits
|
||||
from a specific class or conforms to a protocol or protocol composition.
|
||||
For example, in the generic function below, the generic parameter `T: Comparable`
|
||||
indicates that any type argument substituted
|
||||
for the type parameter `T` must conform to the `Comparable` protocol.
|
||||
|
||||
```swift
|
||||
func simpleMax<T: Comparable>(_ x: T, _ y: T) -> T {
|
||||
if x < y {
|
||||
return y
|
||||
}
|
||||
return x
|
||||
}
|
||||
```
|
||||
|
||||
<!--
|
||||
- test: `generic-params`
|
||||
|
||||
```swifttest
|
||||
-> func simpleMax<T: Comparable>(_ x: T, _ y: T) -> T {
|
||||
if x < y {
|
||||
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.
|
||||
|
||||
```swift
|
||||
simpleMax(17, 42) // T is inferred to be Int
|
||||
simpleMax(3.14159, 2.71828) // T is inferred to be Double
|
||||
```
|
||||
|
||||
<!--
|
||||
- test: `generic-params`
|
||||
|
||||
```swifttest
|
||||
>> let r0 =
|
||||
-> simpleMax(17, 42) // T is inferred to be Int
|
||||
>> assert(r0 == 42)
|
||||
>> let r1 =
|
||||
-> simpleMax(3.14159, 2.71828) // T is inferred to be Double
|
||||
>> assert(r1 == 3.14159)
|
||||
```
|
||||
-->
|
||||
|
||||
<!--
|
||||
Rewrite the above to avoid bare expressions.
|
||||
Tracking bug is <rdar://problem/35301593>
|
||||
-->
|
||||
|
||||
### Integer Generic Parameters
|
||||
|
||||
An *integer generic parameter*
|
||||
acts as a placeholder for an integer value rather than a type.
|
||||
It has the following form:
|
||||
|
||||
```swift
|
||||
let <#type parameter#>: <#type>
|
||||
```
|
||||
|
||||
The *type* must be the `Int` type from the Swift standard library,
|
||||
or a type alias or generic type that resolves to `Int`.
|
||||
|
||||
The value you provide for an integer generic parameter
|
||||
must be either an integer literal
|
||||
or another integer generic parameter from the enclosing generic context.
|
||||
For example:
|
||||
|
||||
```swift
|
||||
struct SomeStruct<let x: Int> { }
|
||||
let a: SomeStruct<2> // OK: integer literal
|
||||
|
||||
struct AnotherStruct<let x: Int, T, each U> {
|
||||
let b: SomeStruct<x> // OK: another integer generic parameter
|
||||
|
||||
static let c = 42
|
||||
let d: SomeStruct<c> // Error: Can't use a constant.
|
||||
|
||||
let e: SomeStruct<T> // Error: Can't use a generic type parameter.
|
||||
let f: SomeStruct<U> // Error: Can't use a parameter pack.
|
||||
}
|
||||
```
|
||||
|
||||
The value of an integer generic parameter on a type
|
||||
is accessible as a static constant member of that type,
|
||||
with the same visibility as the type itself.
|
||||
The value of an integer generic parameter on a function
|
||||
is accessible as a constant from within the function.
|
||||
When used in an expression,
|
||||
these constants have type `Int`.
|
||||
|
||||
```swift
|
||||
print(a.x) // Prints "4"
|
||||
```
|
||||
|
||||
The value of an integer generic parameter can be inferred
|
||||
from the types of the arguments you use
|
||||
when initializing the type or calling the function.
|
||||
|
||||
```swift
|
||||
struct AnotherStruct<let y: Int> {
|
||||
var s: SomeStruct<y>
|
||||
}
|
||||
func someFunction<let z: Int>(s: SomeStruct<z>) {
|
||||
print(z)
|
||||
}
|
||||
|
||||
let s1 = SomeStruct<12>()
|
||||
let s2 = AnotherStruct(s: s1) // AnotherStruct.y is inferred to be 12.
|
||||
someFunction(s: s1) // Prints "12"
|
||||
```
|
||||
|
||||
### Generic Where Clauses
|
||||
|
||||
You can specify additional requirements on type parameters and their associated types
|
||||
by including a generic `where` clause right before the opening curly brace
|
||||
of a type or function's body.
|
||||
A generic `where` clause consists of the `where` keyword,
|
||||
followed by a comma-separated list of one or more *requirements*.
|
||||
|
||||
```swift
|
||||
where <#requirements#>
|
||||
```
|
||||
|
||||
The *requirements* in a generic `where` clause specify that a type parameter inherits from
|
||||
a class or conforms to a protocol or protocol composition.
|
||||
Although the generic `where` clause provides syntactic
|
||||
sugar for expressing simple constraints on type parameters
|
||||
(for example, `<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 example,
|
||||
you can constrain the associated types of type parameters to conform to protocols.
|
||||
For example, `<S: Sequence> where S.Iterator.Element: Equatable`
|
||||
specifies that `S` conforms to the `Sequence` protocol
|
||||
and that the associated type `S.Iterator.Element`
|
||||
conforms to the `Equatable` protocol.
|
||||
This constraint ensures that each element of the sequence is equatable.
|
||||
Integer generic parameters can't have protocol or superclass requirements.
|
||||
|
||||
You can also specify the requirement that two types be identical,
|
||||
using the `==` operator. For example,
|
||||
`<S1: Sequence, S2: Sequence> where S1.Iterator.Element == S2.Iterator.Element`
|
||||
expresses the constraints that `S1` and `S2` conform to the `Sequence` protocol
|
||||
and that the elements of both sequences must be of the same type.
|
||||
For integer generic parameters,
|
||||
the `==` operator specifies a requirement for their values.
|
||||
You can require two integer generic parameters to have the same value,
|
||||
or you can require a specific integer value for the integer generic parameter.
|
||||
|
||||
Any type argument substituted for a type parameter must
|
||||
meet all the constraints and requirements placed on the type parameter.
|
||||
|
||||
A generic `where` clause can appear
|
||||
as part of a declaration that includes type parameters,
|
||||
or as part of a declaration
|
||||
that's nested inside of a declaration that includes type parameters.
|
||||
The generic `where` clause for a nested declaration
|
||||
can still refer to the type parameters of the enclosing declaration;
|
||||
however,
|
||||
the requirements from that `where` clause
|
||||
apply only to the declaration where it's written.
|
||||
|
||||
If the enclosing declaration also has a `where` clause,
|
||||
the requirements from both clauses are combined.
|
||||
In the example below, `startsWithZero()` is available
|
||||
only if `Element` conforms to both `SomeProtocol` and `Numeric`.
|
||||
|
||||
```swift
|
||||
extension Collection where Element: SomeProtocol {
|
||||
func startsWithZero() -> Bool where Element: Numeric {
|
||||
return first == .zero
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
<!--
|
||||
- test: `contextual-where-clauses-combine`
|
||||
|
||||
```swifttest
|
||||
>> protocol SomeProtocol { }
|
||||
>> extension Int: SomeProtocol { }
|
||||
-> extension Collection where Element: SomeProtocol {
|
||||
func startsWithZero() -> Bool where Element: Numeric {
|
||||
return first == .zero
|
||||
}
|
||||
}
|
||||
>> print( [1, 2, 3].startsWithZero() )
|
||||
<< false
|
||||
```
|
||||
-->
|
||||
|
||||
<!--
|
||||
- test: `contextual-where-clause-combine-err`
|
||||
|
||||
```swifttest
|
||||
>> protocol SomeProtocol { }
|
||||
>> extension Bool: SomeProtocol { }
|
||||
|
||||
>> extension Collection where Element: SomeProtocol {
|
||||
>> func returnTrue() -> Bool where Element == Bool {
|
||||
>> return true
|
||||
>> }
|
||||
>> func returnTrue() -> Bool where Element == Int {
|
||||
>> return true
|
||||
>> }
|
||||
>> }
|
||||
!$ error: no type for 'Self.Element' can satisfy both 'Self.Element == Int' and 'Self.Element : SomeProtocol'
|
||||
!! func returnTrue() -> Bool where Element == Int {
|
||||
!! ^
|
||||
```
|
||||
-->
|
||||
|
||||
You can overload a generic function or initializer by providing different
|
||||
constraints, requirements, or both on the type parameters.
|
||||
When you call an overloaded generic function or initializer,
|
||||
the compiler uses these constraints to resolve which overloaded function
|
||||
or initializer to invoke.
|
||||
|
||||
For more information about generic `where` clauses and to see an example
|
||||
of one in a generic function declaration,
|
||||
see <doc:Generics#Generic-Where-Clauses>.
|
||||
|
||||
> Grammar of a generic parameter clause:
|
||||
>
|
||||
> *generic-parameter-clause* → **`<`** *generic-parameter-list* **`>`** \
|
||||
> *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* \
|
||||
> *generic-parameter* → **`let`** *type-name* **`:`** *type* \
|
||||
>
|
||||
> *generic-where-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* \
|
||||
> *same-type-requirement* → *type-identifier* **`==`** *signed-integer-literal*
|
||||
|
||||
<!--
|
||||
NOTE: A conformance requirement can only have one type after the colon,
|
||||
otherwise, you'd have a syntactic ambiguity
|
||||
(a comma-separated list types inside of a comma-separated list of requirements).
|
||||
-->
|
||||
|
||||
## 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:
|
||||
|
||||
```swift
|
||||
<<#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 ---
|
||||
or, for an integer generic parameter,
|
||||
an integer value that replaces that integer generic parameter.
|
||||
The result is a specialized version of that generic type.
|
||||
The example below shows a simplified version of the Swift standard library's
|
||||
generic dictionary type.
|
||||
|
||||
```swift
|
||||
struct Dictionary<Key: Hashable, Value>: Collection, ExpressibleByDictionaryLiteral {
|
||||
/* ... */
|
||||
}
|
||||
```
|
||||
|
||||
<!--
|
||||
TODO: How are we supposed to wrap code lines like the above?
|
||||
-->
|
||||
|
||||
The specialized version of the generic `Dictionary` type, `Dictionary<String, Int>`
|
||||
is formed by replacing the generic parameters `Key: Hashable` and `Value`
|
||||
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 generic `where` clause. In the example above,
|
||||
the `Key` 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's itself
|
||||
a specialized version of a generic type (provided it satisfies the appropriate
|
||||
constraints and requirements). For example, you can replace the type parameter
|
||||
`Element` in `Array<Element>` with a specialized version of an array, `Array<Int>`,
|
||||
to form an array whose elements are themselves arrays of integers.
|
||||
|
||||
```swift
|
||||
let arrayOfArrays: Array<Array<Int>> = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
|
||||
```
|
||||
|
||||
<!--
|
||||
- test: `array-of-arrays`
|
||||
|
||||
```swifttest
|
||||
-> let arrayOfArrays: Array<Array<Int>> = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
|
||||
```
|
||||
-->
|
||||
|
||||
As mentioned in <doc:GenericParametersAndArguments#Generic-Parameter-Clause>,
|
||||
you don't use a generic argument clause to specify the type arguments
|
||||
of a generic function or initializer.
|
||||
|
||||
> Grammar of a generic argument clause:
|
||||
>
|
||||
> *generic-argument-clause* → **`<`** *generic-argument-list* **`>`** \
|
||||
> *generic-argument-list* → *generic-argument* | *generic-argument* **`,`** *generic-argument-list* \
|
||||
> *generic-argument* → *type* | *signed-integer-literal*
|
||||
|
||||
<!--
|
||||
This source file is part of the Swift.org open source project
|
||||
|
||||
Copyright (c) 2014 - 2022 Apple Inc. and the Swift project authors
|
||||
Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
|
||||
See https://swift.org/LICENSE.txt for license information
|
||||
See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
-->
|
||||
1265
skills/programming-swift/ReferenceManual/LexicalStructure.md
Normal file
1265
skills/programming-swift/ReferenceManual/LexicalStructure.md
Normal file
File diff suppressed because it is too large
Load Diff
500
skills/programming-swift/ReferenceManual/Patterns.md
Normal file
500
skills/programming-swift/ReferenceManual/Patterns.md
Normal file
@@ -0,0 +1,500 @@
|
||||
# Patterns
|
||||
|
||||
Match and destructure values.
|
||||
|
||||
A *pattern* represents the structure of a single value
|
||||
or a composite value.
|
||||
For example, the structure of a tuple `(1, 2)` is a comma-separated list of two
|
||||
elements. Because patterns represent the structure of a value rather than any
|
||||
one particular value, you can match them with a variety of values.
|
||||
For instance, the pattern `(x, y)` matches the tuple `(1, 2)` and any other
|
||||
two-element tuple. In addition to matching a pattern with a value,
|
||||
you can extract part or all of a composite value and bind each part
|
||||
to a constant or variable name.
|
||||
|
||||
In Swift, there are two basic kinds of patterns:
|
||||
those that successfully match any kind of value,
|
||||
and those that may fail to match a specified value at runtime.
|
||||
|
||||
The first kind of pattern is used for destructuring values
|
||||
in simple variable, constant, and optional bindings.
|
||||
These include wildcard patterns, identifier patterns,
|
||||
and any value binding or tuple patterns containing
|
||||
them. You can specify a type annotation for these patterns
|
||||
to constrain them to match only values of a certain type.
|
||||
|
||||
The second kind of pattern is used for full pattern matching,
|
||||
where the values you're trying to match against may not be there at runtime.
|
||||
These include enumeration case patterns, optional patterns, expression patterns,
|
||||
and type-casting patterns. You use these patterns in a case label of a `switch`
|
||||
statement, a `catch` clause of a `do` statement,
|
||||
or in the case condition of an `if`, `while`,
|
||||
`guard`, or `for`-`in` statement.
|
||||
|
||||
> Grammar of a pattern:
|
||||
>
|
||||
> *pattern* → *wildcard-pattern* *type-annotation*_?_ \
|
||||
> *pattern* → *identifier-pattern* *type-annotation*_?_ \
|
||||
> *pattern* → *value-binding-pattern* \
|
||||
> *pattern* → *tuple-pattern* *type-annotation*_?_ \
|
||||
> *pattern* → *enum-case-pattern* \
|
||||
> *pattern* → *optional-pattern* \
|
||||
> *pattern* → *type-casting-pattern* \
|
||||
> *pattern* → *expression-pattern*
|
||||
|
||||
## Wildcard Pattern
|
||||
|
||||
A *wildcard pattern* matches and ignores any value and consists of an underscore
|
||||
(`_`). Use a wildcard pattern when you don't care about the values being
|
||||
matched against. For example, the following code iterates through the closed range `1...3`,
|
||||
ignoring the current value of the range on each iteration of the loop:
|
||||
|
||||
```swift
|
||||
for _ in 1...3 {
|
||||
// Do something three times.
|
||||
}
|
||||
```
|
||||
|
||||
<!--
|
||||
- test: `wildcard-pattern`
|
||||
|
||||
```swifttest
|
||||
-> for _ in 1...3 {
|
||||
// Do something three times.
|
||||
}
|
||||
```
|
||||
-->
|
||||
|
||||
> Grammar of a wildcard pattern:
|
||||
>
|
||||
> *wildcard-pattern* → **`_`**
|
||||
|
||||
## Identifier Pattern
|
||||
|
||||
An *identifier pattern* matches any value and binds the matched value to a
|
||||
variable or constant name.
|
||||
For example, in the following constant declaration, `someValue` is an identifier pattern
|
||||
that matches the value `42` of type `Int`:
|
||||
|
||||
```swift
|
||||
let someValue = 42
|
||||
```
|
||||
|
||||
<!--
|
||||
- test: `identifier-pattern`
|
||||
|
||||
```swifttest
|
||||
-> let someValue = 42
|
||||
```
|
||||
-->
|
||||
|
||||
When the match succeeds, the value `42` is bound (assigned)
|
||||
to the constant name `someValue`.
|
||||
|
||||
When the pattern on the left-hand side of a variable or constant declaration
|
||||
is an identifier pattern,
|
||||
the identifier pattern is implicitly a subpattern of a value-binding pattern.
|
||||
|
||||
> Grammar of an identifier pattern:
|
||||
>
|
||||
> *identifier-pattern* → *identifier*
|
||||
|
||||
## Value-Binding Pattern
|
||||
|
||||
A *value-binding pattern* binds matched values to variable or constant names.
|
||||
Value-binding patterns that bind a matched value to the name of a constant
|
||||
begin with the `let` keyword; those that bind to the name of variable
|
||||
begin with the `var` keyword.
|
||||
|
||||
Identifiers patterns within a value-binding pattern
|
||||
bind new named variables or constants to their matching values. For example,
|
||||
you can decompose the elements of a tuple and bind the value of each element to a
|
||||
corresponding identifier pattern.
|
||||
|
||||
```swift
|
||||
let point = (3, 2)
|
||||
switch point {
|
||||
// Bind x and y to the elements of point.
|
||||
case let (x, y):
|
||||
print("The point is at (\(x), \(y)).")
|
||||
}
|
||||
// Prints "The point is at (3, 2)."
|
||||
```
|
||||
|
||||
<!--
|
||||
- test: `value-binding-pattern`
|
||||
|
||||
```swifttest
|
||||
-> let point = (3, 2)
|
||||
-> switch point {
|
||||
// Bind x and y to the elements of point.
|
||||
case let (x, y):
|
||||
print("The point is at (\(x), \(y)).")
|
||||
}
|
||||
<- The point is at (3, 2).
|
||||
```
|
||||
-->
|
||||
|
||||
In the example above, `let` distributes to each identifier pattern in the
|
||||
tuple pattern `(x, y)`. Because of this behavior, the `switch` cases
|
||||
`case let (x, y):` and `case (let x, let y):` match the same values.
|
||||
|
||||
> Grammar of a value-binding pattern:
|
||||
>
|
||||
> *value-binding-pattern* → **`var`** *pattern* | **`let`** *pattern*
|
||||
|
||||
<!--
|
||||
NOTE: We chose to call this "value-binding pattern"
|
||||
instead of "variable pattern",
|
||||
because it's a pattern that binds values to either variables or constants,
|
||||
not a pattern that varies.
|
||||
"Variable pattern" is ambiguous between those two meanings.
|
||||
-->
|
||||
|
||||
## Tuple Pattern
|
||||
|
||||
A *tuple pattern* is a comma-separated list of zero or more patterns, enclosed in
|
||||
parentheses. Tuple patterns match values of corresponding tuple types.
|
||||
|
||||
You can constrain a tuple pattern to match certain kinds of tuple types
|
||||
by using type annotations.
|
||||
For example, the tuple pattern `(x, y): (Int, Int)` in the constant declaration
|
||||
`let (x, y): (Int, Int) = (1, 2)` matches only tuple types in which
|
||||
both elements are of type `Int`.
|
||||
|
||||
When a tuple pattern is used as the pattern in a `for`-`in` statement
|
||||
or in a variable or constant declaration, it can contain only wildcard patterns,
|
||||
identifier patterns, optional patterns, or other tuple patterns that contain those.
|
||||
For example,
|
||||
the following code isn't valid because the element `0` in the tuple pattern `(x, 0)` is
|
||||
an expression pattern:
|
||||
|
||||
```swift
|
||||
let points = [(0, 0), (1, 0), (1, 1), (2, 0), (2, 1)]
|
||||
// This code isn't valid.
|
||||
for (x, 0) in points {
|
||||
/* ... */
|
||||
}
|
||||
```
|
||||
|
||||
<!--
|
||||
- test: `tuple-pattern`
|
||||
|
||||
```swifttest
|
||||
-> let points = [(0, 0), (1, 0), (1, 1), (2, 0), (2, 1)]
|
||||
-> // This code isn't valid.
|
||||
-> for (x, 0) in points {
|
||||
>> _ = x
|
||||
/* ... */
|
||||
}
|
||||
!$ error: expected pattern
|
||||
!! for (x, 0) in points {
|
||||
!! ^
|
||||
```
|
||||
-->
|
||||
|
||||
The parentheses around a tuple pattern that contains a single element have no effect.
|
||||
The pattern matches values of that single element's type. For example, the following are
|
||||
equivalent:
|
||||
|
||||
<!--
|
||||
This test needs to be compiled.
|
||||
The error message in the REPL is unpredictable as of
|
||||
Swift version 1.1 (swift-600.0.54.20)
|
||||
-->
|
||||
|
||||
```swift
|
||||
let a = 2 // a: Int = 2
|
||||
let (a) = 2 // a: Int = 2
|
||||
let (a): Int = 2 // a: Int = 2
|
||||
```
|
||||
|
||||
<!--
|
||||
- test: `single-element-tuple-pattern`
|
||||
|
||||
```swifttest
|
||||
-> let a = 2 // a: Int = 2
|
||||
-> let (a) = 2 // a: Int = 2
|
||||
-> let (a): Int = 2 // a: Int = 2
|
||||
!$ error: invalid redeclaration of 'a'
|
||||
!! let (a) = 2 // a: Int = 2
|
||||
!! ^
|
||||
!$ note: 'a' previously declared here
|
||||
!! let a = 2 // a: Int = 2
|
||||
!! ^
|
||||
!$ error: invalid redeclaration of 'a'
|
||||
!! let (a): Int = 2 // a: Int = 2
|
||||
!! ^
|
||||
!$ note: 'a' previously declared here
|
||||
!! let a = 2 // a: Int = 2
|
||||
!! ^
|
||||
```
|
||||
-->
|
||||
|
||||
> Grammar of a tuple pattern:
|
||||
>
|
||||
> *tuple-pattern* → **`(`** *tuple-pattern-element-list*_?_ **`)`** \
|
||||
> *tuple-pattern-element-list* → *tuple-pattern-element* | *tuple-pattern-element* **`,`** *tuple-pattern-element-list* \
|
||||
> *tuple-pattern-element* → *pattern* | *identifier* **`:`** *pattern*
|
||||
|
||||
## Enumeration Case Pattern
|
||||
|
||||
An *enumeration case pattern* matches a case of an existing enumeration type.
|
||||
Enumeration case patterns appear in `switch` statement
|
||||
case labels and in the case conditions of `if`, `while`, `guard`, and `for`-`in`
|
||||
statements.
|
||||
|
||||
If the enumeration case you're trying to match has any associated values,
|
||||
the corresponding enumeration case pattern must specify a tuple pattern that contains
|
||||
one element for each associated value. For an example that uses a `switch` statement
|
||||
to match enumeration cases containing associated values,
|
||||
see <doc:Enumerations#Associated-Values>.
|
||||
|
||||
An enumeration case pattern also matches
|
||||
values of that case wrapped in an optional.
|
||||
This simplified syntax lets you omit an optional pattern.
|
||||
Note that,
|
||||
because `Optional` is implemented as an enumeration,
|
||||
`.none` and `.some` can appear
|
||||
in the same switch as the cases of the enumeration type.
|
||||
|
||||
```swift
|
||||
enum SomeEnum { case left, right }
|
||||
let x: SomeEnum? = .left
|
||||
switch x {
|
||||
case .left:
|
||||
print("Turn left")
|
||||
case .right:
|
||||
print("Turn right")
|
||||
case nil:
|
||||
print("Keep going straight")
|
||||
}
|
||||
// Prints "Turn left".
|
||||
```
|
||||
|
||||
<!--
|
||||
- test: `enum-pattern-matching-optional`
|
||||
|
||||
```swifttest
|
||||
-> enum SomeEnum { case left, right }
|
||||
-> let x: SomeEnum? = .left
|
||||
-> switch x {
|
||||
case .left:
|
||||
print("Turn left")
|
||||
case .right:
|
||||
print("Turn right")
|
||||
case nil:
|
||||
print("Keep going straight")
|
||||
}
|
||||
<- Turn left
|
||||
```
|
||||
-->
|
||||
|
||||
> Grammar of an enumeration case pattern:
|
||||
>
|
||||
> *enum-case-pattern* → *type-identifier*_?_ **`.`** *enum-case-name* *tuple-pattern*_?_
|
||||
|
||||
## Optional Pattern
|
||||
|
||||
An *optional pattern* matches values wrapped in a `some(Wrapped)` case
|
||||
of an `Optional<Wrapped>` enumeration.
|
||||
Optional patterns consist of an identifier pattern followed immediately by a question mark
|
||||
and appear in the same places as enumeration case patterns.
|
||||
|
||||
Because optional patterns are syntactic sugar for `Optional`
|
||||
enumeration case patterns,
|
||||
the following are equivalent:
|
||||
|
||||
```swift
|
||||
let someOptional: Int? = 42
|
||||
// Match using an enumeration case pattern.
|
||||
if case .some(let x) = someOptional {
|
||||
print(x)
|
||||
}
|
||||
|
||||
// Match using an optional pattern.
|
||||
if case let x? = someOptional {
|
||||
print(x)
|
||||
}
|
||||
```
|
||||
|
||||
<!--
|
||||
- test: `optional-pattern`
|
||||
|
||||
```swifttest
|
||||
-> let someOptional: Int? = 42
|
||||
-> // Match using an enumeration case pattern.
|
||||
-> if case .some(let x) = someOptional {
|
||||
print(x)
|
||||
}
|
||||
<< 42
|
||||
|
||||
-> // Match using an optional pattern.
|
||||
-> if case let x? = someOptional {
|
||||
print(x)
|
||||
}
|
||||
<< 42
|
||||
```
|
||||
-->
|
||||
|
||||
The optional pattern provides a convenient way to
|
||||
iterate over an array of optional values in a `for`-`in` statement,
|
||||
executing the body of the loop only for non-`nil` elements.
|
||||
|
||||
```swift
|
||||
let arrayOfOptionalInts: [Int?] = [nil, 2, 3, nil, 5]
|
||||
// Match only non-nil values.
|
||||
for case let number? in arrayOfOptionalInts {
|
||||
print("Found a \(number)")
|
||||
}
|
||||
// Found a 2
|
||||
// Found a 3
|
||||
// Found a 5
|
||||
```
|
||||
|
||||
<!--
|
||||
- test: `optional-pattern-for-in`
|
||||
|
||||
```swifttest
|
||||
-> let arrayOfOptionalInts: [Int?] = [nil, 2, 3, nil, 5]
|
||||
-> // Match only non-nil values.
|
||||
-> for case let number? in arrayOfOptionalInts {
|
||||
print("Found a \(number)")
|
||||
}
|
||||
</ Found a 2
|
||||
</ Found a 3
|
||||
</ Found a 5
|
||||
```
|
||||
-->
|
||||
|
||||
> Grammar of an optional pattern:
|
||||
>
|
||||
> *optional-pattern* → *identifier-pattern* **`?`**
|
||||
|
||||
## Type-Casting Patterns
|
||||
|
||||
There are two type-casting patterns, the `is` pattern and the `as` pattern.
|
||||
The `is` pattern appears only in `switch` statement
|
||||
case labels. The `is` and `as` patterns have the following form:
|
||||
|
||||
```swift
|
||||
is <#type#>
|
||||
<#pattern#> as <#type#>
|
||||
```
|
||||
|
||||
The `is` pattern matches a value if the type of that value at runtime is the same as
|
||||
the type specified in the right-hand side of the `is` pattern --- or a subclass of that type.
|
||||
The `is` pattern behaves like the `is` operator in that they both perform a type cast
|
||||
but discard the returned type.
|
||||
|
||||
The `as` pattern matches a value if the type of that value at runtime is the same as
|
||||
the type specified in the right-hand side of the `as` pattern --- or a subclass of that type.
|
||||
If the match succeeds,
|
||||
the type of the matched value is cast to the *pattern* specified in the right-hand side
|
||||
of the `as` pattern.
|
||||
|
||||
For an example that uses a `switch` statement
|
||||
to match values with `is` and `as` patterns,
|
||||
see <doc:TypeCasting#Type-Casting-for-Any-and-AnyObject>.
|
||||
|
||||
> Grammar of a type casting pattern:
|
||||
>
|
||||
> *type-casting-pattern* → *is-pattern* | *as-pattern* \
|
||||
> *is-pattern* → **`is`** *type* \
|
||||
> *as-pattern* → *pattern* **`as`** *type*
|
||||
|
||||
## Expression Pattern
|
||||
|
||||
An *expression pattern* represents the value of an expression.
|
||||
Expression patterns appear only in `switch` statement
|
||||
case labels.
|
||||
|
||||
The expression represented by the expression pattern
|
||||
is compared with the value of an input expression
|
||||
using the pattern-matching operator (`~=`) from the Swift standard library.
|
||||
The matches succeeds
|
||||
if the `~=` operator returns `true`. By default, the `~=` operator compares
|
||||
two values of the same type using the `==` operator.
|
||||
It can also match a value with a range of values,
|
||||
by checking whether the value is contained within the range,
|
||||
as the following example shows.
|
||||
|
||||
```swift
|
||||
let point = (1, 2)
|
||||
switch point {
|
||||
case (0, 0):
|
||||
print("(0, 0) is at the origin.")
|
||||
case (-2...2, -2...2):
|
||||
print("(\(point.0), \(point.1)) is near the origin.")
|
||||
default:
|
||||
print("The point is at (\(point.0), \(point.1)).")
|
||||
}
|
||||
// Prints "(1, 2) is near the origin."
|
||||
```
|
||||
|
||||
<!--
|
||||
- test: `expression-pattern`
|
||||
|
||||
```swifttest
|
||||
-> let point = (1, 2)
|
||||
-> switch point {
|
||||
case (0, 0):
|
||||
print("(0, 0) is at the origin.")
|
||||
case (-2...2, -2...2):
|
||||
print("(\(point.0), \(point.1)) is near the origin.")
|
||||
default:
|
||||
print("The point is at (\(point.0), \(point.1)).")
|
||||
}
|
||||
<- (1, 2) is near the origin.
|
||||
```
|
||||
-->
|
||||
|
||||
You can overload the `~=` operator to provide custom expression matching behavior.
|
||||
For example, you can rewrite the above example to compare the `point` expression
|
||||
with a string representations of points.
|
||||
|
||||
```swift
|
||||
// Overload the ~= operator to match a string with an integer.
|
||||
func ~= (pattern: String, value: Int) -> Bool {
|
||||
return pattern == "\(value)"
|
||||
}
|
||||
switch point {
|
||||
case ("0", "0"):
|
||||
print("(0, 0) is at the origin.")
|
||||
default:
|
||||
print("The point is at (\(point.0), \(point.1)).")
|
||||
}
|
||||
// Prints "The point is at (1, 2)."
|
||||
```
|
||||
|
||||
<!--
|
||||
- test: `expression-pattern`
|
||||
|
||||
```swifttest
|
||||
-> // Overload the ~= operator to match a string with an integer.
|
||||
-> func ~= (pattern: String, value: Int) -> Bool {
|
||||
return pattern == "\(value)"
|
||||
}
|
||||
-> switch point {
|
||||
case ("0", "0"):
|
||||
print("(0, 0) is at the origin.")
|
||||
default:
|
||||
print("The point is at (\(point.0), \(point.1)).")
|
||||
}
|
||||
<- The point is at (1, 2).
|
||||
```
|
||||
-->
|
||||
|
||||
> Grammar of an expression pattern:
|
||||
>
|
||||
> *expression-pattern* → *expression*
|
||||
|
||||
<!--
|
||||
This source file is part of the Swift.org open source project
|
||||
|
||||
Copyright (c) 2014 - 2022 Apple Inc. and the Swift project authors
|
||||
Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
|
||||
See https://swift.org/LICENSE.txt for license information
|
||||
See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
-->
|
||||
1456
skills/programming-swift/ReferenceManual/Statements.md
Normal file
1456
skills/programming-swift/ReferenceManual/Statements.md
Normal file
File diff suppressed because it is too large
Load Diff
1107
skills/programming-swift/ReferenceManual/SummaryOfTheGrammar.md
Normal file
1107
skills/programming-swift/ReferenceManual/SummaryOfTheGrammar.md
Normal file
File diff suppressed because it is too large
Load Diff
1407
skills/programming-swift/ReferenceManual/Types.md
Normal file
1407
skills/programming-swift/ReferenceManual/Types.md
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user