3288 lines
96 KiB
Markdown
3288 lines
96 KiB
Markdown
# Expressions
|
|
|
|
Access, modify, and assign values.
|
|
|
|
In Swift, there are four kinds of expressions:
|
|
prefix expressions, infix expressions, primary expressions, and postfix expressions.
|
|
Evaluating an expression returns a value,
|
|
causes a side effect, or both.
|
|
|
|
Prefix and infix expressions let you
|
|
apply operators to smaller expressions.
|
|
Primary expressions are conceptually the simplest kind of expression,
|
|
and they provide a way to access values.
|
|
Postfix expressions,
|
|
like prefix and infix expressions,
|
|
let you build up more complex expressions
|
|
using postfixes such as function calls and member access.
|
|
Each kind of expression is described in detail
|
|
in the sections below.
|
|
|
|
> Grammar of an expression:
|
|
>
|
|
> *expression* → *try-operator*_?_ *await-operator*_?_ *prefix-expression* *infix-expressions*_?_
|
|
|
|
## Prefix Expressions
|
|
|
|
*Prefix expressions* combine
|
|
an optional prefix operator with an expression.
|
|
Prefix operators take one argument,
|
|
the expression that follows them.
|
|
|
|
For information about the behavior of these operators,
|
|
see <doc:BasicOperators> and <doc:AdvancedOperators>.
|
|
|
|
For information about the operators provided by the Swift standard library,
|
|
see [Operator Declarations](https://developer.apple.com/documentation/swift/operator_declarations).
|
|
|
|
> Grammar of a prefix expression:
|
|
>
|
|
> *prefix-expression* → *prefix-operator*_?_ *postfix-expression* \
|
|
> *prefix-expression* → *in-out-expression*
|
|
|
|
### In-Out Expression
|
|
|
|
An *in-out expression* marks a variable
|
|
that's being passed
|
|
as an in-out argument to a function call expression.
|
|
|
|
```swift
|
|
&<#expression#>
|
|
```
|
|
|
|
For more information about in-out parameters and to see an example,
|
|
see <doc:Functions#In-Out-Parameters>.
|
|
|
|
In-out expressions are also used
|
|
when providing a non-pointer argument
|
|
in a context where a pointer is needed,
|
|
as described in <doc:Expressions#Implicit-Conversion-to-a-Pointer-Type>.
|
|
|
|
> Grammar of an in-out expression:
|
|
>
|
|
> *in-out-expression* → **`&`** *primary-expression*
|
|
|
|
### Try Operator
|
|
|
|
A *try expression* consists of the `try` operator
|
|
followed by an expression that can throw an error.
|
|
It has the following form:
|
|
|
|
```swift
|
|
try <#expression#>
|
|
```
|
|
|
|
The value of a `try` expression is the value of the *expression*.
|
|
|
|
An *optional-try expression* consists of the `try?` operator
|
|
followed by an expression that can throw an error.
|
|
It has the following form:
|
|
|
|
```swift
|
|
try? <#expression#>
|
|
```
|
|
|
|
If the *expression* doesn't throw an error,
|
|
the value of the optional-try expression
|
|
is an optional containing the value of the *expression*.
|
|
Otherwise, the value of the optional-try expression is `nil`.
|
|
|
|
A *forced-try expression* consists of the `try!` operator
|
|
followed by an expression that can throw an error.
|
|
It has the following form:
|
|
|
|
```swift
|
|
try! <#expression#>
|
|
```
|
|
|
|
The value of a forced-try expression is the value of the *expression*.
|
|
If the *expression* throws an error,
|
|
a runtime error is produced.
|
|
|
|
When the expression on the left-hand side of an infix operator
|
|
is marked with `try`, `try?`, or `try!`,
|
|
that operator applies to the whole infix expression.
|
|
That said, you can use parentheses to be explicit about the scope of the operator's application.
|
|
|
|
```swift
|
|
// Writing 'try' applies to both function calls.
|
|
sum = try someThrowingFunction() + anotherThrowingFunction()
|
|
|
|
// Writing 'try' applies to both function calls.
|
|
sum = try (someThrowingFunction() + anotherThrowingFunction())
|
|
|
|
// Error: Writing 'try' applies only to the first function call.
|
|
sum = (try someThrowingFunction()) + anotherThrowingFunction()
|
|
```
|
|
|
|
<!--
|
|
- test: `placement-of-try`
|
|
|
|
```swifttest
|
|
>> func someThrowingFunction() throws -> Int { return 10 }
|
|
>> func anotherThrowingFunction() throws -> Int { return 5 }
|
|
>> var sum = 0
|
|
// Writing 'try' applies to both function calls.
|
|
-> sum = try someThrowingFunction() + anotherThrowingFunction()
|
|
|
|
// Writing 'try' applies to both function calls.
|
|
-> sum = try (someThrowingFunction() + anotherThrowingFunction())
|
|
|
|
// Error: Writing 'try' applies only to the first function call.
|
|
-> sum = (try someThrowingFunction()) + anotherThrowingFunction()
|
|
!$ error: call can throw but is not marked with 'try'
|
|
!! sum = (try someThrowingFunction()) + anotherThrowingFunction()
|
|
!! ^~~~~~~~~~~~~~~~~~~~~~~~~
|
|
!$ note: did you mean to use 'try'?
|
|
!! sum = (try someThrowingFunction()) + anotherThrowingFunction()
|
|
!! ^
|
|
!! try
|
|
!$ note: did you mean to handle error as optional value?
|
|
!! sum = (try someThrowingFunction()) + anotherThrowingFunction()
|
|
!! ^
|
|
!! try?
|
|
!$ note: did you mean to disable error propagation?
|
|
!! sum = (try someThrowingFunction()) + anotherThrowingFunction()
|
|
!! ^
|
|
!! try!
|
|
```
|
|
-->
|
|
|
|
A `try` expression can't appear on the right-hand side of an infix operator,
|
|
unless the infix operator is the assignment operator
|
|
or the `try` expression is enclosed in parentheses.
|
|
|
|
<!--
|
|
- test: `try-on-right`
|
|
|
|
```swifttest
|
|
>> func someThrowingFunction() throws -> Int { return 10 }
|
|
>> var sum = 0
|
|
-> sum = 7 + try someThrowingFunction() // Error
|
|
!$ error: 'try' cannot appear to the right of a non-assignment operator
|
|
!! sum = 7 + try someThrowingFunction() // Error
|
|
!! ^
|
|
-> sum = 7 + (try someThrowingFunction()) // OK
|
|
```
|
|
-->
|
|
|
|
If an expression includes both the `try` and `await` operator,
|
|
the `try` operator must appear first.
|
|
|
|
<!--
|
|
The "try await" ordering is also part of the grammar for 'expression',
|
|
but it's important enough to be worth re-stating in prose.
|
|
-->
|
|
|
|
For more information and to see examples of how to use `try`, `try?`, and `try!`,
|
|
see <doc:ErrorHandling>.
|
|
|
|
> Grammar of a try expression:
|
|
>
|
|
> *try-operator* → **`try`** | **`try`** **`?`** | **`try`** **`!`**
|
|
|
|
### Await Operator
|
|
|
|
An *await expression* consists of the `await` operator
|
|
followed by an expression that uses the result of an asynchronous operation.
|
|
It has the following form:
|
|
|
|
```swift
|
|
await <#expression#>
|
|
```
|
|
|
|
The value of an `await` expression is the value of the *expression*.
|
|
|
|
An expression marked with `await` is called a *potential suspension point*.
|
|
Execution of an asynchronous function can be suspended
|
|
at each expression that's marked with `await`.
|
|
In addition,
|
|
execution of concurrent code is never suspended at any other point.
|
|
This means code between potential suspension points
|
|
can safely update state that requires temporarily breaking invariants,
|
|
provided that it completes the update
|
|
before the next potential suspension point.
|
|
|
|
An `await` expression can appear only within an asynchronous context,
|
|
such as the trailing closure passed to the `async(priority:operation:)` function.
|
|
It can't appear in the body of a `defer` statement,
|
|
or in an autoclosure of synchronous function type.
|
|
|
|
When the expression on the left-hand side of an infix operator
|
|
is marked with the `await` operator,
|
|
that operator applies to the whole infix expression.
|
|
That said, you can use parentheses
|
|
to be explicit about the scope of the operator's application.
|
|
|
|
```swift
|
|
// Writing 'await' applies to both function calls.
|
|
sum = await someAsyncFunction() + anotherAsyncFunction()
|
|
|
|
// Writing 'await' applies to both function calls.
|
|
sum = await (someAsyncFunction() + anotherAsyncFunction())
|
|
|
|
// Error: Writing 'await' applies only to the first function call.
|
|
sum = (await someAsyncFunction()) + anotherAsyncFunction()
|
|
```
|
|
|
|
<!--
|
|
- test: `placement-of-await`
|
|
|
|
```swifttest
|
|
>> func someAsyncFunction() async -> Int { return 10 }
|
|
>> func anotherAsyncFunction() async -> Int { return 5 }
|
|
>> func f() async {
|
|
>> var sum = 0
|
|
// Writing 'await' applies to both function calls.
|
|
-> sum = await someAsyncFunction() + anotherAsyncFunction()
|
|
|
|
// Writing 'await' applies to both function calls.
|
|
-> sum = await (someAsyncFunction() + anotherAsyncFunction())
|
|
|
|
// Error: Writing 'await' applies only to the first function call.
|
|
-> sum = (await someAsyncFunction()) + anotherAsyncFunction()
|
|
>> _ = sum // Suppress irrelevant written-but-not-read warning
|
|
>> }
|
|
!$ error: expression is 'async' but is not marked with 'await'
|
|
!! sum = (await someAsyncFunction()) + anotherAsyncFunction()
|
|
!! ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
!! await
|
|
!$ note: call is 'async'
|
|
!! sum = (await someAsyncFunction()) + anotherAsyncFunction()
|
|
!! ^
|
|
```
|
|
-->
|
|
|
|
An `await` expression can't appear on the right-hand side of an infix operator,
|
|
unless the infix operator is the assignment operator
|
|
or the `await` expression is enclosed in parentheses.
|
|
|
|
<!--
|
|
- test: `await-on-right`
|
|
|
|
```swifttest
|
|
>> func f() async {
|
|
>> func someAsyncFunction() async -> Int { return 10 }
|
|
>> var sum = 0
|
|
>> sum = 7 + await someAsyncFunction() // Error
|
|
!$ error: 'await' cannot appear to the right of a non-assignment operator
|
|
!! sum = 7 + await someAsyncFunction() // Error
|
|
!! ^
|
|
>> sum = 7 + (await someAsyncFunction()) // OK
|
|
>> _ = sum // Suppress irrelevant written-but-not-read warning
|
|
>> }
|
|
```
|
|
-->
|
|
|
|
If an expression includes both the `await` and `try` operator,
|
|
the `try` operator must appear first.
|
|
|
|
<!--
|
|
The "try await" ordering is also part of the grammar for 'expression',
|
|
but it's important enough to be worth re-stating in prose.
|
|
-->
|
|
|
|
> Grammar of an await expression:
|
|
>
|
|
> *await-operator* → **`await`**
|
|
|
|
## Infix Expressions
|
|
|
|
*Infix expressions* combine
|
|
an infix binary operator with the expression that it takes
|
|
as its left- and right-hand arguments.
|
|
It has the following form:
|
|
|
|
```swift
|
|
<#left-hand argument#> <#operator#> <#right-hand argument#>
|
|
```
|
|
|
|
For information about the behavior of these operators,
|
|
see <doc:BasicOperators> and <doc:AdvancedOperators>.
|
|
|
|
For information about the operators provided by the Swift standard library,
|
|
see [Operator Declarations](https://developer.apple.com/documentation/swift/operator_declarations).
|
|
|
|
<!--
|
|
You have essentially expression sequences here, and within it are
|
|
parts of the expressions. We're calling them "expressions" even
|
|
though they aren't what we ordinarily think of as expressions. We
|
|
have this two-phase thing where we do the expression sequence parsing
|
|
which gives a rough parse tree. Then after name binding we know
|
|
operator precedence and we do a second phase of parsing that builds
|
|
something that's a more traditional tree.
|
|
-->
|
|
|
|
> Note: At parse time,
|
|
> an expression made up of infix operators is represented
|
|
> as a flat list.
|
|
> This list is transformed into a tree
|
|
> by applying operator precedence.
|
|
> For example, the expression `2 + 3 * 5`
|
|
> is initially understood as a flat list of five items,
|
|
> `2`, `+`, `3`, `*`, and `5`.
|
|
> This process transforms it into the tree (2 + (3 * 5)).
|
|
|
|
> Grammar of an infix expression:
|
|
>
|
|
> *infix-expression* → *infix-operator* *prefix-expression* \
|
|
> *infix-expression* → *assignment-operator* *try-operator*_?_ *await-operator*_?_ *prefix-expression* \
|
|
> *infix-expression* → *conditional-operator* *try-operator*_?_ *await-operator*_?_ *prefix-expression* \
|
|
> *infix-expression* → *type-casting-operator* \
|
|
> *infix-expressions* → *infix-expression* *infix-expressions*_?_
|
|
|
|
### Assignment Operator
|
|
|
|
The *assignment operator* sets a new value
|
|
for a given expression.
|
|
It has the following form:
|
|
|
|
```swift
|
|
<#expression#> = <#value#>
|
|
```
|
|
|
|
The value of the *expression*
|
|
is set to the value obtained by evaluating the *value*.
|
|
If the *expression* is a tuple,
|
|
the *value* must be a tuple
|
|
with the same number of elements.
|
|
(Nested tuples are allowed.)
|
|
Assignment is performed from each part of the *value*
|
|
to the corresponding part of the *expression*.
|
|
For example:
|
|
|
|
```swift
|
|
(a, _, (b, c)) = ("test", 9.45, (12, 3))
|
|
// a is "test", b is 12, c is 3, and 9.45 is ignored
|
|
```
|
|
|
|
<!--
|
|
- test: `assignmentOperator`
|
|
|
|
```swifttest
|
|
>> var (a, _, (b, c)) = ("test", 9.45, (12, 3))
|
|
-> (a, _, (b, c)) = ("test", 9.45, (12, 3))
|
|
/> a is \"\(a)\", b is \(b), c is \(c), and 9.45 is ignored
|
|
</ a is "test", b is 12, c is 3, and 9.45 is ignored
|
|
```
|
|
-->
|
|
|
|
The assignment operator doesn't return any value.
|
|
|
|
> Grammar of an assignment operator:
|
|
>
|
|
> *assignment-operator* → **`=`**
|
|
|
|
### Ternary Conditional Operator
|
|
|
|
The *ternary conditional operator* evaluates to one of two given values
|
|
based on the value of a condition.
|
|
It has the following form:
|
|
|
|
```swift
|
|
<#condition#> ? <#expression used if true#> : <#expression used if false#>
|
|
```
|
|
|
|
If the *condition* evaluates to `true`,
|
|
the conditional operator evaluates the first expression
|
|
and returns its value.
|
|
Otherwise, it evaluates the second expression
|
|
and returns its value.
|
|
The unused expression isn't evaluated.
|
|
|
|
For an example that uses the ternary conditional operator,
|
|
see <doc:BasicOperators#Ternary-Conditional-Operator>.
|
|
|
|
> Grammar of a conditional operator:
|
|
>
|
|
> *conditional-operator* → **`?`** *expression* **`:`**
|
|
|
|
### Type-Casting Operators
|
|
|
|
There are four type-casting operators:
|
|
the `is` operator,
|
|
the `as` operator,
|
|
the `as?` operator,
|
|
and the `as!` operator.
|
|
|
|
They have the following form:
|
|
|
|
```swift
|
|
<#expression#> is <#type#>
|
|
<#expression#> as <#type#>
|
|
<#expression#> as? <#type#>
|
|
<#expression#> as! <#type#>
|
|
```
|
|
|
|
The `is` operator checks at runtime whether the *expression*
|
|
can be cast to the specified *type*.
|
|
It returns `true` if the *expression* can be cast to the specified *type*;
|
|
otherwise, it returns `false`.
|
|
|
|
<!--
|
|
- test: `triviallyTrueIsAndAs`
|
|
|
|
```swifttest
|
|
-> assert("hello" is String)
|
|
-> assert(!("hello" is Int))
|
|
!$ warning: 'is' test is always true
|
|
!! assert("hello" is String)
|
|
!! ^
|
|
!$ warning: cast from 'String' to unrelated type 'Int' always fails
|
|
!! assert(!("hello" is Int))
|
|
!! ~~~~~~~ ^ ~~~
|
|
```
|
|
-->
|
|
|
|
<!--
|
|
- test: `is-operator-tautology`
|
|
|
|
```swifttest
|
|
-> class Base {}
|
|
-> class Subclass: Base {}
|
|
-> var s = Subclass()
|
|
-> var b = Base()
|
|
|
|
-> assert(s is Base)
|
|
!$ warning: 'is' test is always true
|
|
!! assert(s is Base)
|
|
!! ^
|
|
```
|
|
-->
|
|
|
|
The `as` operator performs a cast
|
|
when it's known at compile time
|
|
that the cast always succeeds,
|
|
such as upcasting or bridging.
|
|
Upcasting lets you use an expression as an instance of its type's supertype,
|
|
without using an intermediate variable.
|
|
The following approaches are equivalent:
|
|
|
|
```swift
|
|
func f(_ any: Any) { print("Function for Any") }
|
|
func f(_ int: Int) { print("Function for Int") }
|
|
let x = 10
|
|
f(x)
|
|
// Prints "Function for Int".
|
|
|
|
let y: Any = x
|
|
f(y)
|
|
// Prints "Function for Any".
|
|
|
|
f(x as Any)
|
|
// Prints "Function for Any".
|
|
```
|
|
|
|
<!--
|
|
- test: `explicit-type-with-as-operator`
|
|
|
|
```swifttest
|
|
-> func f(_ any: Any) { print("Function for Any") }
|
|
-> func f(_ int: Int) { print("Function for Int") }
|
|
-> let x = 10
|
|
-> f(x)
|
|
<- Function for Int
|
|
|
|
-> let y: Any = x
|
|
-> f(y)
|
|
<- Function for Any
|
|
|
|
-> f(x as Any)
|
|
<- Function for Any
|
|
```
|
|
-->
|
|
|
|
Bridging lets you use an expression of
|
|
a Swift standard library type such as `String`
|
|
as its corresponding Foundation type such as `NSString`
|
|
without needing to create a new instance.
|
|
For more information on bridging,
|
|
see [Working with Foundation Types](https://developer.apple.com/documentation/swift/imported_c_and_objective_c_apis/working_with_foundation_types).
|
|
|
|
The `as?` operator
|
|
performs a conditional cast of the *expression*
|
|
to the specified *type*.
|
|
The `as?` operator returns an optional of the specified *type*.
|
|
At runtime, if the cast succeeds,
|
|
the value of *expression* is wrapped in an optional and returned;
|
|
otherwise, the value returned is `nil`.
|
|
If casting to the specified *type*
|
|
is guaranteed to fail or is guaranteed to succeed,
|
|
a compile-time error is raised.
|
|
|
|
The `as!` operator performs a forced cast of the *expression* to the specified *type*.
|
|
The `as!` operator returns a value of the specified *type*, not an optional type.
|
|
If the cast fails, a runtime error is raised.
|
|
The behavior of `x as! T` is the same as the behavior of `(x as? T)!`.
|
|
|
|
For more information about type casting
|
|
and to see examples that use the type-casting operators,
|
|
see <doc:TypeCasting>.
|
|
|
|
> Grammar of a type-casting operator:
|
|
>
|
|
> *type-casting-operator* → **`is`** *type* \
|
|
> *type-casting-operator* → **`as`** *type* \
|
|
> *type-casting-operator* → **`as`** **`?`** *type* \
|
|
> *type-casting-operator* → **`as`** **`!`** *type*
|
|
|
|
## Primary Expressions
|
|
|
|
*Primary expressions*
|
|
are the most basic kind of expression.
|
|
They can be used as expressions on their own,
|
|
and they can be combined with other tokens
|
|
to make prefix expressions, infix expressions, and postfix expressions.
|
|
|
|
> Grammar of a primary expression:
|
|
>
|
|
> *primary-expression* → *identifier* *generic-argument-clause*_?_ \
|
|
> *primary-expression* → *literal-expression* \
|
|
> *primary-expression* → *self-expression* \
|
|
> *primary-expression* → *superclass-expression* \
|
|
> *primary-expression* → *conditional-expression* \
|
|
> *primary-expression* → *closure-expression* \
|
|
> *primary-expression* → *parenthesized-expression* \
|
|
> *primary-expression* → *tuple-expression* \
|
|
> *primary-expression* → *implicit-member-expression* \
|
|
> *primary-expression* → *wildcard-expression* \
|
|
> *primary-expression* → *macro-expansion-expression* \
|
|
> *primary-expression* → *key-path-expression* \
|
|
> *primary-expression* → *selector-expression* \
|
|
> *primary-expression* → *key-path-string-expression*
|
|
|
|
<!--
|
|
NOTE: One reason for breaking primary expressions out of postfix
|
|
expressions is for exposition -- it makes it easier to organize the
|
|
prose surrounding the production rules.
|
|
-->
|
|
|
|
<!--
|
|
TR: Is a generic argument clause allowed
|
|
after an identifier in expression context?
|
|
It seems like that should only occur when an identifier
|
|
is a *type* identifier.
|
|
-->
|
|
|
|
### Literal Expression
|
|
|
|
A *literal expression* consists of
|
|
either an ordinary literal (such as a string or a number),
|
|
an array or dictionary literal,
|
|
or a playground literal.
|
|
|
|
> Note:
|
|
> Prior to Swift 5.9,
|
|
> the following special literals were recognized:
|
|
> `#column`,
|
|
> `#dsohandle`,
|
|
> `#fileID`,
|
|
> `#filePath`,
|
|
> `#file`,
|
|
> `#function`,
|
|
> and `#line`.
|
|
> These are now implemented as macros in the Swift standard library:
|
|
> [`column()`](https://developer.apple.com/documentation/swift/column()),
|
|
> [`dsohandle()`](https://developer.apple.com/documentation/swift/dsohandle()),
|
|
> [`fileID()`](https://developer.apple.com/documentation/swift/fileID()),
|
|
> [`filePath()`](https://developer.apple.com/documentation/swift/filePath()),
|
|
> [`file()`](https://developer.apple.com/documentation/swift/file()),
|
|
> [`function()`](https://developer.apple.com/documentation/swift/function()),
|
|
> and [`line()`](https://developer.apple.com/documentation/swift/line()).
|
|
|
|
<!--
|
|
- test: `pound-file-flavors`
|
|
|
|
```swifttest
|
|
>> print(#file == #filePath)
|
|
<< true
|
|
>> print(#file == #fileID)
|
|
<< false
|
|
```
|
|
-->
|
|
|
|
An *array literal* is
|
|
an ordered collection of values.
|
|
It has the following form:
|
|
|
|
```swift
|
|
[<#value 1#>, <#value 2#>, <#...#>]
|
|
```
|
|
|
|
The last expression in the array can be followed by an optional comma.
|
|
The value of an array literal has type `[T]`,
|
|
where `T` is the type of the expressions inside it.
|
|
If there are expressions of multiple types,
|
|
`T` is their closest common supertype.
|
|
Empty array literals are written using an empty
|
|
pair of square brackets and can be used to create an empty array of a specified type.
|
|
|
|
```swift
|
|
var emptyArray: [Double] = []
|
|
```
|
|
|
|
<!--
|
|
- test: `array-literal-brackets`
|
|
|
|
```swifttest
|
|
-> var emptyArray: [Double] = []
|
|
```
|
|
-->
|
|
|
|
A *dictionary literal* is
|
|
an unordered collection of key-value pairs.
|
|
It has the following form:
|
|
|
|
```swift
|
|
[<#key 1#>: <#value 1#>, <#key 2#>: <#value 2#>, <#...#>]
|
|
```
|
|
|
|
The last expression in the dictionary can be followed by an optional comma.
|
|
The value of a dictionary literal has type `[Key: Value]`,
|
|
where `Key` is the type of its key expressions
|
|
and `Value` is the type of its value expressions.
|
|
If there are expressions of multiple types,
|
|
`Key` and `Value` are the closest common supertype
|
|
for their respective values.
|
|
An empty dictionary literal is written as
|
|
a colon inside a pair of brackets (`[:]`)
|
|
to distinguish it from an empty array literal.
|
|
You can use an empty dictionary literal to create an empty dictionary literal
|
|
of specified key and value types.
|
|
|
|
```swift
|
|
var emptyDictionary: [String: Double] = [:]
|
|
```
|
|
|
|
<!--
|
|
- test: `dictionary-literal-brackets`
|
|
|
|
```swifttest
|
|
-> var emptyDictionary: [String: Double] = [:]
|
|
```
|
|
-->
|
|
|
|
A *playground literal*
|
|
is used by Xcode to create an interactive representation
|
|
of a color, file, or image within the program editor.
|
|
Playground literals in plain text outside of Xcode
|
|
are represented using a special literal syntax.
|
|
|
|
For information on using playground literals in Xcode,
|
|
see [Add a color, file, or image literal](https://help.apple.com/xcode/mac/current/#/dev4c60242fc)
|
|
in Xcode Help.
|
|
|
|
> Grammar of a literal expression:
|
|
>
|
|
> *literal-expression* → *literal* \
|
|
> *literal-expression* → *array-literal* | *dictionary-literal* | *playground-literal*
|
|
>
|
|
> *array-literal* → **`[`** *array-literal-items*_?_ **`]`** \
|
|
> *array-literal-items* → *array-literal-item* **`,`**_?_ | *array-literal-item* **`,`** *array-literal-items* \
|
|
> *array-literal-item* → *expression*
|
|
>
|
|
> *dictionary-literal* → **`[`** *dictionary-literal-items* **`]`** | **`[`** **`:`** **`]`** \
|
|
> *dictionary-literal-items* → *dictionary-literal-item* **`,`**_?_ | *dictionary-literal-item* **`,`** *dictionary-literal-items* \
|
|
> *dictionary-literal-item* → *expression* **`:`** *expression*
|
|
>
|
|
> *playground-literal* → **`#colorLiteral`** **`(`** **`red`** **`:`** *expression* **`,`** **`green`** **`:`** *expression* **`,`** **`blue`** **`:`** *expression* **`,`** **`alpha`** **`:`** *expression* **`)`** \
|
|
> *playground-literal* → **`#fileLiteral`** **`(`** **`resourceName`** **`:`** *expression* **`)`** \
|
|
> *playground-literal* → **`#imageLiteral`** **`(`** **`resourceName`** **`:`** *expression* **`)`**
|
|
|
|
### Self Expression
|
|
|
|
The `self` expression is an explicit reference to the current type
|
|
or instance of the type in which it occurs.
|
|
It has the following forms:
|
|
|
|
```swift
|
|
self
|
|
self.<#member name#>
|
|
self[<#subscript index#>]
|
|
self(<#initializer arguments#>)
|
|
self.init(<#initializer arguments#>)
|
|
```
|
|
|
|
<!--
|
|
TODO: Come back and explain the second to last form (i.e., self(arg: value)).
|
|
-->
|
|
|
|
In an initializer, subscript, or instance method, `self` refers to the current
|
|
instance of the type in which it occurs. In a type method,
|
|
`self` refers to the current type in which it occurs.
|
|
|
|
The `self` expression is used to specify scope when accessing members,
|
|
providing disambiguation when there's
|
|
another variable of the same name in scope,
|
|
such as a function parameter.
|
|
For example:
|
|
|
|
```swift
|
|
class SomeClass {
|
|
var greeting: String
|
|
init(greeting: String) {
|
|
self.greeting = greeting
|
|
}
|
|
}
|
|
```
|
|
|
|
<!--
|
|
- test: `self-expression`
|
|
|
|
```swifttest
|
|
-> class SomeClass {
|
|
var greeting: String
|
|
init(greeting: String) {
|
|
self.greeting = greeting
|
|
}
|
|
}
|
|
```
|
|
-->
|
|
|
|
In a mutating method of a value type,
|
|
you can assign a new instance of that value type to `self`.
|
|
For example:
|
|
|
|
```swift
|
|
struct Point {
|
|
var x = 0.0, y = 0.0
|
|
mutating func moveBy(x deltaX: Double, y deltaY: Double) {
|
|
self = Point(x: x + deltaX, y: y + deltaY)
|
|
}
|
|
}
|
|
```
|
|
|
|
<!--
|
|
- test: `self-expression`
|
|
|
|
```swifttest
|
|
-> struct Point {
|
|
var x = 0.0, y = 0.0
|
|
mutating func moveBy(x deltaX: Double, y deltaY: Double) {
|
|
self = Point(x: x + deltaX, y: y + deltaY)
|
|
}
|
|
}
|
|
>> var somePoint = Point(x: 1.0, y: 1.0)
|
|
>> somePoint.moveBy(x: 2.0, y: 3.0)
|
|
>> print("The point is now at (\(somePoint.x), \(somePoint.y))")
|
|
<< The point is now at (3.0, 4.0)
|
|
```
|
|
-->
|
|
|
|
<!-- Apple Books screenshot begins here. -->
|
|
|
|
> Grammar of a self expression:
|
|
>
|
|
> *self-expression* → **`self`** | *self-method-expression* | *self-subscript-expression* | *self-initializer-expression*
|
|
>
|
|
> *self-method-expression* → **`self`** **`.`** *identifier* \
|
|
> *self-subscript-expression* → **`self`** **`[`** *function-call-argument-list* **`]`** \
|
|
> *self-initializer-expression* → **`self`** **`.`** **`init`**
|
|
|
|
### Superclass Expression
|
|
|
|
A *superclass expression* lets a class
|
|
interact with its superclass.
|
|
It has one of the following forms:
|
|
|
|
```swift
|
|
super.<#member name#>
|
|
super[<#subscript index#>]
|
|
super.init(<#initializer arguments#>)
|
|
```
|
|
|
|
The first form is used to access a member of the superclass.
|
|
The second form is used to access the superclass's subscript implementation.
|
|
The third form is used to access an initializer of the superclass.
|
|
|
|
Subclasses can use a superclass expression
|
|
in their implementation of members, subscripting, and initializers
|
|
to make use of the implementation in their superclass.
|
|
|
|
> Grammar of a superclass expression:
|
|
>
|
|
> *superclass-expression* → *superclass-method-expression* | *superclass-subscript-expression* | *superclass-initializer-expression*
|
|
>
|
|
> *superclass-method-expression* → **`super`** **`.`** *identifier* \
|
|
> *superclass-subscript-expression* → **`super`** **`[`** *function-call-argument-list* **`]`** \
|
|
> *superclass-initializer-expression* → **`super`** **`.`** **`init`**
|
|
|
|
### Conditional Expression
|
|
|
|
A *conditional expression* evaluates to one of several given values
|
|
based on the value of a condition.
|
|
It has one the following forms:
|
|
|
|
```swift
|
|
if <#condition 1#> {
|
|
<#expression used if condition 1 is true#>
|
|
} else if <#condition 2#> {
|
|
<#expression used if condition 2 is true#>
|
|
} else {
|
|
<#expression used if both conditions are false#>
|
|
}
|
|
|
|
switch <#expression#> {
|
|
case <#pattern 1#>:
|
|
<#expression 1#>
|
|
case <#pattern 2#> where <#condition#>:
|
|
<#expression 2#>
|
|
default:
|
|
<#expression 3#>
|
|
}
|
|
```
|
|
|
|
A conditional expression
|
|
has the same behavior and syntax as an `if` statement or a `switch` statement,
|
|
except for the differences that the paragraphs below describe.
|
|
|
|
A conditional expression appears only in the following contexts:
|
|
|
|
- As the value assigned to a variable.
|
|
- As the initial value in a variable or constant declaration.
|
|
- As the error thrown by a `throw` expression.
|
|
- As the value returned by a function, closure, or property getter.
|
|
- As the value inside a branch of a conditional expression.
|
|
|
|
The branches of a conditional expression are exhaustive,
|
|
ensuring that the expression always produces a value
|
|
regardless of the condition.
|
|
This means each `if` branch needs a corresponding `else` branch.
|
|
|
|
Each branch contains either a single expression,
|
|
which is used as the value for the conditional expression
|
|
when that branch's conditional is true,
|
|
a `throw` statement,
|
|
or a call to a function that never returns.
|
|
|
|
Each branch must produce a value of the same type.
|
|
Because type checking of each branch is independent,
|
|
you sometimes need to specify the value's type explicitly,
|
|
like when branches include different kinds of literals,
|
|
or when a branch's value is `nil`.
|
|
When you need to provide this information,
|
|
add a type annotation to the variable that the result is assigned to,
|
|
or add an `as` cast to the branches' values.
|
|
|
|
```swift
|
|
let number: Double = if someCondition { 10 } else { 12.34 }
|
|
let number = if someCondition { 10 as Double } else { 12.34 }
|
|
```
|
|
|
|
Inside a result builder,
|
|
conditional expressions can appear
|
|
only as the initial value of a variable or constant.
|
|
This behavior means when you write `if` or `switch` in a result builder ---
|
|
outside of a variable or constant declaration ---
|
|
that code is understood as a branch statement
|
|
and one of the result builder's methods transforms that code.
|
|
|
|
Don't put a conditional expression in a `try` expression,
|
|
even if one of the branches of a conditional expression is throwing.
|
|
|
|
> Grammar of a conditional expression:
|
|
>
|
|
> *conditional-expression* → *if-expression* | *switch-expression*
|
|
>
|
|
> *if-expression* → **`if`** *condition-list* **`{`** *statement* **`}`** *if-expression-tail* \
|
|
> *if-expression-tail* → **`else`** *if-expression* \
|
|
> *if-expression-tail* → **`else`** **`{`** *statement* **`}`**
|
|
>
|
|
> *switch-expression* → **`switch`** *expression* **`{`** *switch-expression-cases* **`}`** \
|
|
> *switch-expression-cases* → *switch-expression-case* *switch-expression-cases*_?_ \
|
|
> *switch-expression-case* → *case-label* *statement* \
|
|
> *switch-expression-case* → *default-label* *statement*
|
|
|
|
### Closure Expression
|
|
|
|
A *closure expression* creates a closure,
|
|
also known as a *lambda* or an *anonymous function*
|
|
in other programming languages.
|
|
Like a function declaration,
|
|
a closure contains statements,
|
|
and it captures constants and variables from its enclosing scope.
|
|
It has the following form:
|
|
|
|
```swift
|
|
{ (<#parameters#>) -> <#return type#> in
|
|
<#statements#>
|
|
}
|
|
```
|
|
|
|
The *parameters* have the same form
|
|
as the parameters in a function declaration,
|
|
as described in <doc:Declarations#Function-Declaration>.
|
|
|
|
Writing `throws` or `async` in a closure expression
|
|
explicitly marks a closure as throwing or asynchronous.
|
|
|
|
```swift
|
|
{ (<#parameters#>) async throws -> <#return type#> in
|
|
<#statements#>
|
|
}
|
|
```
|
|
|
|
If the body of a closure includes a `throws` statement or a `try` expression
|
|
that isn't nested inside of a `do` statement with exhaustive error handling,
|
|
the closure is understood to be throwing.
|
|
If a throwing closure throws errors of only a single type,
|
|
the closure is understood as throwing that error type;
|
|
otherwise, it's understood as throwing `any Error`.
|
|
Likewise, if the body includes an `await` expression,
|
|
it's understood to be asynchronous.
|
|
|
|
There are several special forms
|
|
that allow closures to be written more concisely:
|
|
|
|
<!-- Apple Books screenshot ends here. -->
|
|
|
|
- A closure can omit the types
|
|
of its parameters, its return type, or both.
|
|
If you omit the parameter names and both types,
|
|
omit the `in` keyword before the statements.
|
|
If the omitted types can't be inferred,
|
|
a compile-time error is raised.
|
|
- A closure may omit names for its parameters.
|
|
Its parameters are then implicitly named
|
|
`$` followed by their position:
|
|
`$0`, `$1`, `$2`, and so on.
|
|
- A closure that consists of only a single expression
|
|
is understood to return the value of that expression.
|
|
The contents of this expression are also considered
|
|
when performing type inference on the surrounding expression.
|
|
|
|
The following closure expressions are equivalent:
|
|
|
|
```swift
|
|
myFunction { (x: Int, y: Int) -> Int in
|
|
return x + y
|
|
}
|
|
|
|
myFunction { x, y in
|
|
return x + y
|
|
}
|
|
|
|
myFunction { return $0 + $1 }
|
|
|
|
myFunction { $0 + $1 }
|
|
```
|
|
|
|
<!--
|
|
- test: `closure-expression-forms`
|
|
|
|
```swifttest
|
|
>> func myFunction(f: (Int, Int) -> Int) {}
|
|
-> myFunction { (x: Int, y: Int) -> Int in
|
|
return x + y
|
|
}
|
|
|
|
-> myFunction { x, y in
|
|
return x + y
|
|
}
|
|
|
|
-> myFunction { return $0 + $1 }
|
|
|
|
-> myFunction { $0 + $1 }
|
|
```
|
|
-->
|
|
|
|
For information about passing a closure as an argument to a function,
|
|
see <doc:Expressions#Function-Call-Expression>.
|
|
|
|
Closure expressions can be used
|
|
without being stored in a variable or constant,
|
|
such as when you immediately use a closure as part of a function call.
|
|
The closure expressions passed to `myFunction` in code above are
|
|
examples of this kind of immediate use.
|
|
As a result,
|
|
whether a closure expression is escaping or nonescaping depends
|
|
on the surrounding context of the expression.
|
|
A closure expression is nonescaping
|
|
if it's called immediately
|
|
or passed as a nonescaping function argument.
|
|
Otherwise, the closure expression is escaping.
|
|
|
|
For more information about escaping closures, see <doc:Closures#Escaping-Closures>.
|
|
|
|
#### Capture Lists
|
|
|
|
By default, a closure expression captures
|
|
constants and variables from its surrounding scope
|
|
with strong references to those values.
|
|
You can use a *capture list* to explicitly control
|
|
how values are captured in a closure.
|
|
|
|
A capture list is written as a comma-separated list of expressions
|
|
surrounded by square brackets,
|
|
before the list of parameters.
|
|
If you use a capture list, you must also use the `in` keyword,
|
|
even if you omit the parameter names, parameter types, and return type.
|
|
|
|
The entries in the capture list are initialized
|
|
when the closure is created.
|
|
For each entry in the capture list,
|
|
a constant is initialized
|
|
to the value of the constant or variable that has the same name
|
|
in the surrounding scope.
|
|
For example in the code below,
|
|
`a` is included in the capture list but `b` is not,
|
|
which gives them different behavior.
|
|
|
|
```swift
|
|
var a = 0
|
|
var b = 0
|
|
let closure = { [a] in
|
|
print(a, b)
|
|
}
|
|
|
|
a = 10
|
|
b = 10
|
|
closure()
|
|
// Prints "0 10".
|
|
```
|
|
|
|
<!--
|
|
- test: `capture-list-value-semantics`
|
|
|
|
```swifttest
|
|
-> var a = 0
|
|
-> var b = 0
|
|
-> let closure = { [a] in
|
|
print(a, b)
|
|
}
|
|
|
|
-> a = 10
|
|
-> b = 10
|
|
-> closure()
|
|
<- 0 10
|
|
```
|
|
-->
|
|
|
|
There are two different things named `a`,
|
|
the variable in the surrounding scope
|
|
and the constant in the closure's scope,
|
|
but only one variable named `b`.
|
|
The `a` in the inner scope is initialized
|
|
with the value of the `a` in the outer scope
|
|
when the closure is created,
|
|
but their values aren't connected in any special way.
|
|
This means that a change to the value of `a` in the outer scope
|
|
doesn't affect the value of `a` in the inner scope,
|
|
nor does a change to `a` inside the closure
|
|
affect the value of `a` outside the closure.
|
|
In contrast, there's only one variable named `b` ---
|
|
the `b` in the outer scope ---
|
|
so changes from inside or outside the closure are visible in both places.
|
|
|
|
<!--
|
|
[Contributor 6004] also describes the distinction as
|
|
"capturing the variable, not the value"
|
|
but he notes that we don't have a rigorous definition of
|
|
capturing a variable in Swift
|
|
(unlike some other languages)
|
|
so that description's not likely to be very helpful for developers.
|
|
-->
|
|
|
|
This distinction isn't visible
|
|
when the captured variable's type has reference semantics.
|
|
For example,
|
|
there are two things named `x` in the code below,
|
|
a variable in the outer scope and a constant in the inner scope,
|
|
but they both refer to the same object
|
|
because of reference semantics.
|
|
|
|
```swift
|
|
class SimpleClass {
|
|
var value: Int = 0
|
|
}
|
|
var x = SimpleClass()
|
|
var y = SimpleClass()
|
|
let closure = { [x] in
|
|
print(x.value, y.value)
|
|
}
|
|
|
|
x.value = 10
|
|
y.value = 10
|
|
closure()
|
|
// Prints "10 10".
|
|
```
|
|
|
|
<!--
|
|
- test: `capture-list-reference-semantics`
|
|
|
|
```swifttest
|
|
-> class SimpleClass {
|
|
var value: Int = 0
|
|
}
|
|
-> var x = SimpleClass()
|
|
-> var y = SimpleClass()
|
|
-> let closure = { [x] in
|
|
print(x.value, y.value)
|
|
}
|
|
|
|
-> x.value = 10
|
|
-> y.value = 10
|
|
-> closure()
|
|
<- 10 10
|
|
```
|
|
-->
|
|
|
|
<!--
|
|
- test: `capture-list-with-commas`
|
|
|
|
```swifttest
|
|
-> var x = 100
|
|
-> var y = 7
|
|
-> var f: () -> Int = { [x, y] in x+y }
|
|
>> let r0 = f()
|
|
>> assert(r0 == 107)
|
|
```
|
|
-->
|
|
|
|
<!--
|
|
It's not an error to capture things that aren't included in the capture list,
|
|
although maybe it should be. See also rdar://17024367.
|
|
-->
|
|
|
|
<!--
|
|
- test: `capture-list-is-not-exhaustive`
|
|
|
|
```swifttest
|
|
-> var x = 100
|
|
var y = 7
|
|
var f: () -> Int = { [x] in x }
|
|
var g: () -> Int = { [x] in x+y }
|
|
|
|
-> let r0 = f()
|
|
-> assert(r0 == 100)
|
|
-> let r1 = g()
|
|
-> assert(r1 == 107)
|
|
```
|
|
-->
|
|
|
|
If the type of the expression's value is a class,
|
|
you can mark the expression in a capture list
|
|
with `weak` or `unowned` to capture a weak or unowned reference
|
|
to the expression's value.
|
|
|
|
```swift
|
|
myFunction { print(self.title) } // implicit strong capture
|
|
myFunction { [self] in print(self.title) } // explicit strong capture
|
|
myFunction { [weak self] in print(self!.title) } // weak capture
|
|
myFunction { [unowned self] in print(self.title) } // unowned capture
|
|
```
|
|
|
|
<!--
|
|
- test: `closure-expression-weak`
|
|
|
|
```swifttest
|
|
>> func myFunction(f: () -> Void) { f() }
|
|
>> class C {
|
|
>> let title = "Title"
|
|
>> func method() {
|
|
-> myFunction { print(self.title) } // implicit strong capture
|
|
-> myFunction { [self] in print(self.title) } // explicit strong capture
|
|
-> myFunction { [weak self] in print(self!.title) } // weak capture
|
|
-> myFunction { [unowned self] in print(self.title) } // unowned capture
|
|
>> } }
|
|
>> C().method()
|
|
<< Title
|
|
<< Title
|
|
<< Title
|
|
<< Title
|
|
```
|
|
-->
|
|
|
|
You can also bind an arbitrary expression
|
|
to a named value in a capture list.
|
|
The expression is evaluated when the closure is created,
|
|
and the value is captured with the specified strength.
|
|
For example:
|
|
|
|
```swift
|
|
// Weak capture of "self.parent" as "parent"
|
|
myFunction { [weak parent = self.parent] in print(parent!.title) }
|
|
```
|
|
|
|
<!--
|
|
- test: `closure-expression-capture`
|
|
|
|
```swifttest
|
|
>> func myFunction(f: () -> Void) { f() }
|
|
>> class P { let title = "Title" }
|
|
>> class C {
|
|
>> let parent = P()
|
|
>> func method() {
|
|
// Weak capture of "self.parent" as "parent"
|
|
-> myFunction { [weak parent = self.parent] in print(parent!.title) }
|
|
>> } }
|
|
>> C().method()
|
|
<< Title
|
|
```
|
|
-->
|
|
|
|
For more information and examples of closure expressions,
|
|
see <doc:Closures#Closure-Expressions>.
|
|
For more information and examples of capture lists,
|
|
see <doc:AutomaticReferenceCounting#Resolving-Strong-Reference-Cycles-for-Closures>.
|
|
|
|
<!--
|
|
- test: `async-throwing-closure-syntax`
|
|
|
|
```swifttest
|
|
>> var a = 12
|
|
>> let c1 = { [a] in return a } // OK: No async or throws
|
|
>> let c2 = { [a] async in return a } // Error
|
|
>> let c3 = { [a] async -> in return a } // Error
|
|
>> let c4 = { [a] () async -> Int in return a } // OK: Has () and ->
|
|
!$ error: expected expression
|
|
!! let c3 = { [a] async -> in return a } // Error
|
|
!! ^
|
|
!$ error: unable to infer type of a closure parameter 'async' in the current context
|
|
!! let c2 = { [a] async in return a } // Error
|
|
!! ^
|
|
// NOTE: The error message for c3 gets printed by the REPL before the c2 error.
|
|
```
|
|
-->
|
|
|
|
> Grammar of a closure expression:
|
|
>
|
|
> *closure-expression* → **`{`** *attributes*_?_ *closure-signature*_?_ *statements*_?_ **`}`**
|
|
>
|
|
> *closure-signature* → *capture-list*_?_ *closure-parameter-clause* **`async`**_?_ *throws-clause*_?_ *function-result*_?_ **`in`** \
|
|
> *closure-signature* → *capture-list* **`in`**
|
|
>
|
|
> *closure-parameter-clause* → **`(`** **`)`** | **`(`** *closure-parameter-list* **`)`** | *identifier-list* \
|
|
> *closure-parameter-list* → *closure-parameter* | *closure-parameter* **`,`** *closure-parameter-list* \
|
|
> *closure-parameter* → *closure-parameter-name* *type-annotation*_?_ \
|
|
> *closure-parameter* → *closure-parameter-name* *type-annotation* **`...`** \
|
|
> *closure-parameter-name* → *identifier*
|
|
>
|
|
> *capture-list* → **`[`** *capture-list-items* **`]`** \
|
|
> *capture-list-items* → *capture-list-item* | *capture-list-item* **`,`** *capture-list-items* \
|
|
> *capture-list-item* → *capture-specifier*_?_ *identifier* \
|
|
> *capture-list-item* → *capture-specifier*_?_ *identifier* **`=`** *expression* \
|
|
> *capture-list-item* → *capture-specifier*_?_ *self-expression* \
|
|
> *capture-specifier* → **`weak`** | **`unowned`** | **`unowned(safe)`** | **`unowned(unsafe)`**
|
|
|
|
### Implicit Member Expression
|
|
|
|
An *implicit member expression*
|
|
is an abbreviated way to access a member of a type,
|
|
such as an enumeration case or a type method,
|
|
in a context where type inference
|
|
can determine the implied type.
|
|
It has the following form:
|
|
|
|
```swift
|
|
.<#member name#>
|
|
```
|
|
|
|
For example:
|
|
|
|
```swift
|
|
var x = MyEnumeration.someValue
|
|
x = .anotherValue
|
|
```
|
|
|
|
<!--
|
|
- test: `implicitMemberEnum`
|
|
|
|
```swifttest
|
|
>> enum MyEnumeration { case someValue, anotherValue }
|
|
-> var x = MyEnumeration.someValue
|
|
-> x = .anotherValue
|
|
```
|
|
-->
|
|
|
|
If the inferred type is an optional,
|
|
you can also use a member of the non-optional type
|
|
in an implicit member expression.
|
|
|
|
```swift
|
|
var someOptional: MyEnumeration? = .someValue
|
|
```
|
|
|
|
<!--
|
|
- test: `implicitMemberEnum`
|
|
|
|
```swifttest
|
|
-> var someOptional: MyEnumeration? = .someValue
|
|
```
|
|
-->
|
|
|
|
Implicit member expressions can be followed by
|
|
a postfix operator or other postfix syntax listed in
|
|
<doc:Expressions#Postfix-Expressions>.
|
|
This is called a *chained implicit member expression*.
|
|
Although it's common for all of the chained postfix expressions
|
|
to have the same type,
|
|
the only requirement is that the whole chained implicit member expression
|
|
needs to be convertible to the type implied by its context.
|
|
Specifically,
|
|
if the implied type is an optional
|
|
you can use a value of the non-optional type,
|
|
and if the implied type is a class type
|
|
you can use a value of one of its subclasses.
|
|
For example:
|
|
|
|
```swift
|
|
class SomeClass {
|
|
static var shared = SomeClass()
|
|
static var sharedSubclass = SomeSubclass()
|
|
var a = AnotherClass()
|
|
}
|
|
class SomeSubclass: SomeClass { }
|
|
class AnotherClass {
|
|
static var s = SomeClass()
|
|
func f() -> SomeClass { return AnotherClass.s }
|
|
}
|
|
let x: SomeClass = .shared.a.f()
|
|
let y: SomeClass? = .shared
|
|
let z: SomeClass = .sharedSubclass
|
|
```
|
|
|
|
<!--
|
|
- test: `implicit-member-chain`
|
|
|
|
```swifttest
|
|
-> class SomeClass {
|
|
static var shared = SomeClass()
|
|
static var sharedSubclass = SomeSubclass()
|
|
var a = AnotherClass()
|
|
}
|
|
-> class SomeSubclass: SomeClass { }
|
|
-> class AnotherClass {
|
|
static var s = SomeClass()
|
|
func f() -> SomeClass { return AnotherClass.s }
|
|
}
|
|
-> let x: SomeClass = .shared.a.f()
|
|
-> let y: SomeClass? = .shared
|
|
-> let z: SomeClass = .sharedSubclass
|
|
```
|
|
-->
|
|
|
|
In the code above,
|
|
the type of `x` matches the type implied by its context exactly,
|
|
the type of `y` is convertible from `SomeClass` to `SomeClass?`,
|
|
and the type of `z` is convertible from `SomeSubclass` to `SomeClass`.
|
|
|
|
> Grammar of an implicit member expression:
|
|
>
|
|
> *implicit-member-expression* → **`.`** *identifier* \
|
|
> *implicit-member-expression* → **`.`** *identifier* **`.`** *postfix-expression*
|
|
|
|
<!--
|
|
The grammar above allows the additional pieces tested below,
|
|
which work even though they're omitted from the SE-0287 list.
|
|
The grammar also overproduces, allowing any primary expression
|
|
because of the definition of postfix-expression.
|
|
-->
|
|
|
|
<!--
|
|
- test: `implicit-member-grammar`
|
|
|
|
```swifttest
|
|
// self expression
|
|
>> enum E { case left, right }
|
|
>> let e: E = .left
|
|
>> let e2: E = .left.self
|
|
>> assert(e == e2)
|
|
|
|
// postfix operator
|
|
>> postfix operator ~
|
|
>> extension E {
|
|
>> static postfix func ~ (e: E) -> E {
|
|
>> switch e {
|
|
>> case .left: return .right
|
|
>> case .right: return .left
|
|
>> }
|
|
>> }
|
|
>> }
|
|
>> let e3: E = .left~
|
|
>> assert(e3 == .right)
|
|
|
|
// initializer expression
|
|
>> class S {
|
|
>> var num: Int
|
|
>> init(bestNumber: Int) { self.num = bestNumber }
|
|
>> }
|
|
>> let s: S = .init(bestNumber: 42)
|
|
```
|
|
-->
|
|
|
|
### Parenthesized Expression
|
|
|
|
A *parenthesized expression* consists of
|
|
an expression surrounded by parentheses.
|
|
You can use parentheses to specify the precedence of operations
|
|
by explicitly grouping expressions.
|
|
Grouping parentheses don't change an expression's type ---
|
|
for example, the type of `(1)` is simply `Int`.
|
|
|
|
<!--
|
|
See "Tuple Expression" below for langref grammar.
|
|
-->
|
|
|
|
> Grammar of a parenthesized expression:
|
|
>
|
|
> *parenthesized-expression* → **`(`** *expression* **`)`**
|
|
|
|
### Tuple Expression
|
|
|
|
A *tuple expression* consists of
|
|
a comma-separated list of expressions surrounded by parentheses.
|
|
Each expression can have an optional identifier before it,
|
|
separated by a colon (`:`).
|
|
It has the following form:
|
|
|
|
```swift
|
|
(<#identifier 1#>: <#expression 1#>, <#identifier 2#>: <#expression 2#>, <#...#>)
|
|
```
|
|
|
|
Each identifier in a tuple expression must be unique
|
|
within the scope of the tuple expression.
|
|
In a nested tuple expression,
|
|
identifiers at the same level of nesting must be unique.
|
|
For example,
|
|
`(a: 10, a: 20)` is invalid
|
|
because the label `a` appears twice at the same level.
|
|
However, `(a: 10, b: (a: 1, x: 2))` is valid ---
|
|
although `a` appears twice,
|
|
it appears once in the outer tuple and once in the inner tuple.
|
|
|
|
<!--
|
|
- test: `tuple-labels-must-be-unique`
|
|
|
|
```swifttest
|
|
>> let bad = (a: 10, a: 20)
|
|
>> let good = (a: 10, b: (a: 1, x: 2))
|
|
!$ error: cannot create a tuple with a duplicate element label
|
|
!! let bad = (a: 10, a: 20)
|
|
!! ^
|
|
```
|
|
-->
|
|
|
|
A tuple expression can contain zero expressions,
|
|
or it can contain two or more expressions.
|
|
A single expression inside parentheses is a parenthesized expression.
|
|
|
|
> Note: Both an empty tuple expression and an empty tuple type
|
|
> are written `()` in Swift.
|
|
> Because `Void` is a type alias for `()`,
|
|
> you can use it to write an empty tuple type.
|
|
> However, like all type aliases, `Void` is always a type ---
|
|
> you can't use it to write an empty tuple expression.
|
|
|
|
> Grammar of a tuple expression:
|
|
>
|
|
> *tuple-expression* → **`(`** **`)`** | **`(`** *tuple-element* **`,`** *tuple-element-list* **`)`** \
|
|
> *tuple-element-list* → *tuple-element* | *tuple-element* **`,`** *tuple-element-list* \
|
|
> *tuple-element* → *expression* | *identifier* **`:`** *expression*
|
|
|
|
### Wildcard Expression
|
|
|
|
A *wildcard expression*
|
|
is used to explicitly ignore a value during an assignment.
|
|
For example, in the following assignment
|
|
10 is assigned to `x` and 20 is ignored:
|
|
|
|
```swift
|
|
(x, _) = (10, 20)
|
|
// x is 10, and 20 is ignored
|
|
```
|
|
|
|
<!--
|
|
- test: `wildcardTuple`
|
|
|
|
```swifttest
|
|
>> var (x, _) = (10, 20)
|
|
-> (x, _) = (10, 20)
|
|
-> // x is 10, and 20 is ignored
|
|
```
|
|
-->
|
|
|
|
> Grammar of a wildcard expression:
|
|
>
|
|
> *wildcard-expression* → **`_`**
|
|
|
|
### Macro-Expansion Expression
|
|
|
|
A *macro-expansion expression* consists of a macro name
|
|
followed by a comma-separated list of the macro's arguments in parentheses.
|
|
The macro is expanded at compile time.
|
|
Macro-expansion expressions have the following form:
|
|
|
|
```swift
|
|
<#macro name#>(<#macro argument 1#>, <#macro argument 2#>)
|
|
```
|
|
|
|
A macro-expansion expression omits the parentheses after the macro's name
|
|
if the macro doesn't take any arguments.
|
|
|
|
A macro-expansion expression can appear as the default value for a parameter.
|
|
When used as the default value of a function or method parameter,
|
|
macros are evaluated using the source code location of the call site,
|
|
not the location where they appear in a function definition.
|
|
However, when a default value is a larger expression
|
|
that contains a macro in addition to other code,
|
|
those macros are evaluated where they appear in the function definition.
|
|
|
|
```swift
|
|
func f(a: Int = #line, b: Int = (#line), c: Int = 100 + #line) {
|
|
print(a, b, c)
|
|
}
|
|
f() // Prints "4 1 101"
|
|
```
|
|
|
|
In the function above,
|
|
the default value for `a` is a single macro expression,
|
|
so that macro is evaluated using the source code location
|
|
where `f(a:b:c:)` is called.
|
|
In contrast, the values for `b` and `c`
|
|
are expressions that contain a macro ---
|
|
the macros in those expressions are evaluated
|
|
using the source code location where `f(a:b:c:)` is defined.
|
|
|
|
When you use a macro as a default value,
|
|
it's type checked without expanding the macro,
|
|
to check the following requirements:
|
|
|
|
- The macro's access level
|
|
is the same as or less restrictive than the function that uses it.
|
|
- The macro either takes no arguments,
|
|
or its arguments are literals without string interpolation.
|
|
- The macro's return type matches the parameter's type.
|
|
|
|
You use macro expressions to call freestanding macros.
|
|
To call an attached macro,
|
|
use the custom attribute syntax described in <doc:Attributes>.
|
|
Both freestanding and attached macros expand as follows:
|
|
|
|
1. Swift parses the source code
|
|
to produce an abstract syntax tree (AST).
|
|
|
|
2. The macro implementation receives AST nodes as its input
|
|
and performs the transformations needed by that macro.
|
|
|
|
3. The transformed AST nodes that the macro implementation produced
|
|
are added to the original AST.
|
|
|
|
The expansion of each macro is independent and self-contained.
|
|
However, as a performance optimization,
|
|
Swift might start an external process that implements the macro
|
|
and reuse the same process to expand multiple macros.
|
|
When you implement a macro,
|
|
that code must not depend on what macros your code previously expanded,
|
|
or on any other external state like the current time.
|
|
|
|
For nested macros and attached macros that have multiple roles,
|
|
the expansion process repeats.
|
|
Nested macro-expansion expressions expand from the outside in.
|
|
For example, in the code below
|
|
`outerMacro(_:)` expands first and the unexpanded call to `innerMacro(_:)`
|
|
appears in the abstract syntax tree
|
|
that `outerMacro(_:)` receives as its input.
|
|
|
|
```swift
|
|
#outerMacro(12, #innerMacro(34), "some text")
|
|
```
|
|
|
|
An attached macro that has multiple roles expands once for each role.
|
|
Each expansion receives the same, original, AST as its input.
|
|
Swift forms the overall expansion
|
|
by collecting all of the generated AST nodes
|
|
and putting them in their corresponding places in the AST.
|
|
|
|
For an overview of macros in Swift, see <doc:Macros>.
|
|
|
|
> Grammar of a macro-expansion expression:
|
|
>
|
|
> *macro-expansion-expression* → **`#`** *identifier* *generic-argument-clause*_?_ *function-call-argument-clause*_?_ *trailing-closures*_?_
|
|
|
|
### Key-Path Expression
|
|
|
|
A *key-path expression*
|
|
refers to a property or subscript of a type.
|
|
You use key-path expressions
|
|
in dynamic programming tasks,
|
|
such as key-value observing.
|
|
They have the following form:
|
|
|
|
```swift
|
|
\<#type name#>.<#path#>
|
|
```
|
|
|
|
The *type name* is the name of a concrete type,
|
|
including any generic parameters,
|
|
such as `String`, `[Int]`, or `Set<Int>`.
|
|
|
|
The *path* consists of
|
|
property names, subscripts, optional-chaining expressions,
|
|
and forced unwrapping expressions.
|
|
Each of these key-path components
|
|
can be repeated as many times as needed,
|
|
in any order.
|
|
|
|
At compile time, a key-path expression
|
|
is replaced by an instance
|
|
of the [`KeyPath`](https://developer.apple.com/documentation/swift/keypath) class.
|
|
|
|
To access a value using a key path,
|
|
pass the key path to the `subscript(keyPath:)` subscript,
|
|
which is available on all types.
|
|
For example:
|
|
|
|
<!--
|
|
The subscript name subscript(keyPath:) above is a little odd,
|
|
but it matches what would be displayed on the web.
|
|
There isn't actually an extension on Any that implements this subscript;
|
|
it's a special case in the compiler.
|
|
-->
|
|
|
|
```swift
|
|
struct SomeStructure {
|
|
var someValue: Int
|
|
}
|
|
|
|
let s = SomeStructure(someValue: 12)
|
|
let pathToProperty = \SomeStructure.someValue
|
|
|
|
let value = s[keyPath: pathToProperty]
|
|
// value is 12
|
|
```
|
|
|
|
<!--
|
|
- test: `keypath-expression`
|
|
|
|
```swifttest
|
|
-> struct SomeStructure {
|
|
var someValue: Int
|
|
}
|
|
|
|
-> let s = SomeStructure(someValue: 12)
|
|
-> let pathToProperty = \SomeStructure.someValue
|
|
|
|
-> let value = s[keyPath: pathToProperty]
|
|
/> value is \(value)
|
|
</ value is 12
|
|
```
|
|
-->
|
|
|
|
The *type name* can be omitted
|
|
in contexts where type inference
|
|
can determine the implied type.
|
|
The following code uses `\.someProperty`
|
|
instead of `\SomeClass.someProperty`:
|
|
|
|
```swift
|
|
class SomeClass: NSObject {
|
|
@objc dynamic var someProperty: Int
|
|
init(someProperty: Int) {
|
|
self.someProperty = someProperty
|
|
}
|
|
}
|
|
|
|
let c = SomeClass(someProperty: 10)
|
|
c.observe(\.someProperty) { object, change in
|
|
// ...
|
|
}
|
|
```
|
|
|
|
<!--
|
|
- test: `keypath-expression-implicit-type-name`
|
|
|
|
```swifttest
|
|
>> import Foundation
|
|
-> class SomeClass: NSObject {
|
|
-> @objc dynamic var someProperty: Int
|
|
-> init(someProperty: Int) {
|
|
-> self.someProperty = someProperty
|
|
-> }
|
|
-> }
|
|
|
|
-> let c = SomeClass(someProperty: 10)
|
|
>> let r0 =
|
|
-> c.observe(\.someProperty) { object, change in
|
|
// ...
|
|
}
|
|
```
|
|
-->
|
|
|
|
<!--
|
|
Rewrite the above to avoid discarding the function's return value.
|
|
Tracking bug is <rdar://problem/35301593>
|
|
-->
|
|
|
|
The *path* can refer to `self` to create the identity key path (`\.self`).
|
|
The identity key path refers to a whole instance,
|
|
so you can use it to access and change all of the data stored in a variable
|
|
in a single step.
|
|
For example:
|
|
|
|
```swift
|
|
var compoundValue = (a: 1, b: 2)
|
|
// Equivalent to compoundValue = (a: 10, b: 20)
|
|
compoundValue[keyPath: \.self] = (a: 10, b: 20)
|
|
```
|
|
|
|
<!--
|
|
- test: `keypath-expression-self-keypath`
|
|
|
|
```swifttest
|
|
-> var compoundValue = (a: 1, b: 2)
|
|
// Equivalent to compoundValue = (a: 10, b: 20)
|
|
-> compoundValue[keyPath: \.self] = (a: 10, b: 20)
|
|
```
|
|
-->
|
|
|
|
The *path* can contain multiple property names,
|
|
separated by periods,
|
|
to refer to a property of a property's value.
|
|
This code uses the key path expression
|
|
`\OuterStructure.outer.someValue`
|
|
to access the `someValue` property
|
|
of the `OuterStructure` type's `outer` property:
|
|
|
|
```swift
|
|
struct OuterStructure {
|
|
var outer: SomeStructure
|
|
init(someValue: Int) {
|
|
self.outer = SomeStructure(someValue: someValue)
|
|
}
|
|
}
|
|
|
|
let nested = OuterStructure(someValue: 24)
|
|
let nestedKeyPath = \OuterStructure.outer.someValue
|
|
|
|
let nestedValue = nested[keyPath: nestedKeyPath]
|
|
// nestedValue is 24
|
|
```
|
|
|
|
<!--
|
|
- test: `keypath-expression`
|
|
|
|
```swifttest
|
|
-> struct OuterStructure {
|
|
var outer: SomeStructure
|
|
init(someValue: Int) {
|
|
self.outer = SomeStructure(someValue: someValue)
|
|
}
|
|
}
|
|
|
|
-> let nested = OuterStructure(someValue: 24)
|
|
-> let nestedKeyPath = \OuterStructure.outer.someValue
|
|
|
|
-> let nestedValue = nested[keyPath: nestedKeyPath]
|
|
/> nestedValue is \(nestedValue)
|
|
</ nestedValue is 24
|
|
```
|
|
-->
|
|
|
|
The *path* can include subscripts using brackets,
|
|
as long as the subscript's parameter type conforms to the `Hashable` protocol.
|
|
This example uses a subscript in a key path
|
|
to access the second element of an array:
|
|
|
|
```swift
|
|
let greetings = ["hello", "hola", "bonjour", "안녕"]
|
|
let myGreeting = greetings[keyPath: \[String].[1]]
|
|
// myGreeting is 'hola'
|
|
```
|
|
|
|
<!--
|
|
- test: `keypath-expression`
|
|
|
|
```swifttest
|
|
-> let greetings = ["hello", "hola", "bonjour", "안녕"]
|
|
-> let myGreeting = greetings[keyPath: \[String].[1]]
|
|
/> myGreeting is '\(myGreeting)'
|
|
</ myGreeting is 'hola'
|
|
```
|
|
-->
|
|
|
|
<!--
|
|
TODO: Update examples here and below to remove type names once
|
|
inference bugs are fixed. The compiler currently gives an error
|
|
that the usage is ambiguous.
|
|
<rdar://problem/34376681> [SR-5865]: Key path expression is "ambiguous without more context"
|
|
-->
|
|
|
|
The value used in a subscript can be a named value or a literal.
|
|
Values are captured in key paths using value semantics.
|
|
The following code uses the variable `index`
|
|
in both a key-path expression and in a closure to access
|
|
the third element of the `greetings` array.
|
|
When `index` is modified,
|
|
the key-path expression still references the third element,
|
|
while the closure uses the new index.
|
|
|
|
```swift
|
|
var index = 2
|
|
let path = \[String].[index]
|
|
let fn: ([String]) -> String = { strings in strings[index] }
|
|
|
|
print(greetings[keyPath: path])
|
|
// Prints "bonjour".
|
|
print(fn(greetings))
|
|
// Prints "bonjour".
|
|
|
|
// Setting 'index' to a new value doesn't affect 'path'
|
|
index += 1
|
|
print(greetings[keyPath: path])
|
|
// Prints "bonjour".
|
|
|
|
// Because 'fn' closes over 'index', it uses the new value
|
|
print(fn(greetings))
|
|
// Prints "안녕".
|
|
```
|
|
|
|
<!--
|
|
- test: `keypath-expression`
|
|
|
|
```swifttest
|
|
-> var index = 2
|
|
-> let path = \[String].[index]
|
|
-> let fn: ([String]) -> String = { strings in strings[index] }
|
|
|
|
-> print(greetings[keyPath: path])
|
|
<- bonjour
|
|
-> print(fn(greetings))
|
|
<- bonjour
|
|
|
|
// Setting 'index' to a new value doesn't affect 'path'
|
|
-> index += 1
|
|
-> print(greetings[keyPath: path])
|
|
<- bonjour
|
|
|
|
// Because 'fn' closes over 'index', it uses the new value
|
|
-> print(fn(greetings))
|
|
<- 안녕
|
|
```
|
|
-->
|
|
|
|
The *path* can use optional chaining and forced unwrapping.
|
|
This code uses optional chaining in a key path
|
|
to access a property of an optional string:
|
|
|
|
```swift
|
|
let firstGreeting: String? = greetings.first
|
|
print(firstGreeting?.count as Any)
|
|
// Prints "Optional(5)".
|
|
|
|
// Do the same thing using a key path.
|
|
let count = greetings[keyPath: \[String].first?.count]
|
|
print(count as Any)
|
|
// Prints "Optional(5)".
|
|
```
|
|
|
|
<!--
|
|
- test: `keypath-expression`
|
|
|
|
```swifttest
|
|
-> let firstGreeting: String? = greetings.first
|
|
-> print(firstGreeting?.count as Any)
|
|
<- Optional(5)
|
|
|
|
// Do the same thing using a key path.
|
|
-> let count = greetings[keyPath: \[String].first?.count]
|
|
-> print(count as Any)
|
|
<- Optional(5)
|
|
```
|
|
-->
|
|
|
|
<!--
|
|
The test above is failing, which appears to be a compiler bug.
|
|
<rdar://problem/58484319> Swift 5.2 regression in keypaths
|
|
-->
|
|
|
|
You can mix and match components of key paths to access values
|
|
that are deeply nested within a type.
|
|
The following code accesses different values and properties
|
|
of a dictionary of arrays
|
|
by using key-path expressions
|
|
that combine these components.
|
|
|
|
```swift
|
|
let interestingNumbers = ["prime": [2, 3, 5, 7, 11, 13, 17],
|
|
"triangular": [1, 3, 6, 10, 15, 21, 28],
|
|
"hexagonal": [1, 6, 15, 28, 45, 66, 91]]
|
|
print(interestingNumbers[keyPath: \[String: [Int]].["prime"]] as Any)
|
|
// Prints "Optional([2, 3, 5, 7, 11, 13, 17])".
|
|
print(interestingNumbers[keyPath: \[String: [Int]].["prime"]![0]])
|
|
// Prints "2".
|
|
print(interestingNumbers[keyPath: \[String: [Int]].["hexagonal"]!.count])
|
|
// Prints "7".
|
|
print(interestingNumbers[keyPath: \[String: [Int]].["hexagonal"]!.count.bitWidth])
|
|
// Prints "64".
|
|
```
|
|
|
|
<!--
|
|
- test: `keypath-expression`
|
|
|
|
```swifttest
|
|
-> let interestingNumbers = ["prime": [2, 3, 5, 7, 11, 13, 17],
|
|
"triangular": [1, 3, 6, 10, 15, 21, 28],
|
|
"hexagonal": [1, 6, 15, 28, 45, 66, 91]]
|
|
-> print(interestingNumbers[keyPath: \[String: [Int]].["prime"]] as Any)
|
|
<- Optional([2, 3, 5, 7, 11, 13, 17])
|
|
-> print(interestingNumbers[keyPath: \[String: [Int]].["prime"]![0]])
|
|
<- 2
|
|
-> print(interestingNumbers[keyPath: \[String: [Int]].["hexagonal"]!.count])
|
|
<- 7
|
|
-> print(interestingNumbers[keyPath: \[String: [Int]].["hexagonal"]!.count.bitWidth])
|
|
<- 64
|
|
```
|
|
-->
|
|
|
|
You can use a key path expression
|
|
in contexts where you would normally provide a function or closure.
|
|
Specifically,
|
|
you can use a key path expression
|
|
whose root type is `SomeType`
|
|
and whose path produces a value of type `Value`,
|
|
instead of a function or closure of type `(SomeType) -> Value`.
|
|
|
|
```swift
|
|
struct Task {
|
|
var description: String
|
|
var completed: Bool
|
|
}
|
|
var toDoList = [
|
|
Task(description: "Practice ping-pong.", completed: false),
|
|
Task(description: "Buy a pirate costume.", completed: true),
|
|
Task(description: "Visit Boston in the Fall.", completed: false),
|
|
]
|
|
|
|
// Both approaches below are equivalent.
|
|
let descriptions = toDoList.filter(\.completed).map(\.description)
|
|
let descriptions2 = toDoList.filter { $0.completed }.map { $0.description }
|
|
```
|
|
|
|
<!--
|
|
- test: `keypath-expression`
|
|
|
|
```swifttest
|
|
-> struct Task {
|
|
var description: String
|
|
var completed: Bool
|
|
}
|
|
-> var toDoList = [
|
|
Task(description: "Practice ping-pong.", completed: false),
|
|
Task(description: "Buy a pirate costume.", completed: true),
|
|
Task(description: "Visit Boston in the Fall.", completed: false),
|
|
]
|
|
|
|
// Both approaches below are equivalent.
|
|
-> let descriptions = toDoList.filter(\.completed).map(\.description)
|
|
-> let descriptions2 = toDoList.filter { $0.completed }.map { $0.description }
|
|
>> assert(descriptions == descriptions2)
|
|
```
|
|
-->
|
|
|
|
<!--
|
|
REFERENCE
|
|
The to-do list above draws from the lyrics of the song
|
|
"The Pirates Who Don't Do Anything".
|
|
-->
|
|
|
|
Any side effects of a key path expression
|
|
are evaluated only at the point where the expression is evaluated.
|
|
For example,
|
|
if you make a function call inside a subscript in a key path expression,
|
|
the function is called only once as part of evaluating the expression,
|
|
not every time the key path is used.
|
|
|
|
```swift
|
|
func makeIndex() -> Int {
|
|
print("Made an index")
|
|
return 0
|
|
}
|
|
// The line below calls makeIndex().
|
|
let taskKeyPath = \[Task][makeIndex()]
|
|
// Prints "Made an index".
|
|
|
|
// Using taskKeyPath doesn't call makeIndex() again.
|
|
let someTask = toDoList[keyPath: taskKeyPath]
|
|
```
|
|
|
|
<!--
|
|
- test: `keypath-expression`
|
|
|
|
```swifttest
|
|
-> func makeIndex() -> Int {
|
|
print("Made an index")
|
|
return 0
|
|
}
|
|
// The line below calls makeIndex().
|
|
-> let taskKeyPath = \[Task][makeIndex()]
|
|
<- Made an index
|
|
>> print(type(of: taskKeyPath))
|
|
<< WritableKeyPath<Array<Task>, Task>
|
|
|
|
// Using taskKeyPath doesn't call makeIndex() again.
|
|
-> let someTask = toDoList[keyPath: taskKeyPath]
|
|
```
|
|
-->
|
|
|
|
For more information about using key paths
|
|
in code that interacts with Objective-C APIs,
|
|
see [Using Objective-C Runtime Features in Swift](https://developer.apple.com/documentation/swift/using_objective_c_runtime_features_in_swift).
|
|
For information about key-value coding and key-value observing,
|
|
see [Key-Value Coding Programming Guide](https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/KeyValueCoding/index.html#//apple_ref/doc/uid/10000107i)
|
|
and [Key-Value Observing Programming Guide](https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/KeyValueObserving/KeyValueObserving.html#//apple_ref/doc/uid/10000177i).
|
|
|
|
> Grammar of a key-path expression:
|
|
>
|
|
> *key-path-expression* → **`\`** *type*_?_ **`.`** *key-path-components* \
|
|
> *key-path-components* → *key-path-component* | *key-path-component* **`.`** *key-path-components* \
|
|
> *key-path-component* → *identifier* *key-path-postfixes*_?_ | *key-path-postfixes*
|
|
>
|
|
> *key-path-postfixes* → *key-path-postfix* *key-path-postfixes*_?_ \
|
|
> *key-path-postfix* → **`?`** | **`!`** | **`self`** | **`[`** *function-call-argument-list* **`]`**
|
|
|
|
### Selector Expression
|
|
|
|
A selector expression lets you access the selector
|
|
used to refer to a method or to a property's
|
|
getter or setter in Objective-C.
|
|
It has the following form:
|
|
|
|
```swift
|
|
#selector(<#method name#>)
|
|
#selector(getter: <#property name#>)
|
|
#selector(setter: <#property name#>)
|
|
```
|
|
|
|
The *method name* and *property name* must be a reference to a method or a property
|
|
that's available in the Objective-C runtime.
|
|
The value of a selector expression is an instance of the `Selector` type.
|
|
For example:
|
|
|
|
```swift
|
|
class SomeClass: NSObject {
|
|
@objc let property: String
|
|
|
|
@objc(doSomethingWithInt:)
|
|
func doSomething(_ x: Int) { }
|
|
|
|
init(property: String) {
|
|
self.property = property
|
|
}
|
|
}
|
|
let selectorForMethod = #selector(SomeClass.doSomething(_:))
|
|
let selectorForPropertyGetter = #selector(getter: SomeClass.property)
|
|
```
|
|
|
|
<!--
|
|
- test: `selector-expression`
|
|
|
|
```swifttest
|
|
>> import Foundation
|
|
-> class SomeClass: NSObject {
|
|
-> @objc let property: String
|
|
|
|
-> @objc(doSomethingWithInt:)
|
|
func doSomething(_ x: Int) { }
|
|
|
|
init(property: String) {
|
|
self.property = property
|
|
}
|
|
}
|
|
-> let selectorForMethod = #selector(SomeClass.doSomething(_:))
|
|
-> let selectorForPropertyGetter = #selector(getter: SomeClass.property)
|
|
```
|
|
-->
|
|
|
|
When creating a selector for a property's getter,
|
|
the *property name* can be a reference to a variable or constant property.
|
|
In contrast, when creating a selector for a property's setter,
|
|
the *property name* must be a reference to a variable property only.
|
|
|
|
The *method name* can contain parentheses for grouping,
|
|
as well the `as` operator to disambiguate between methods that share a name
|
|
but have different type signatures.
|
|
For example:
|
|
|
|
```swift
|
|
extension SomeClass {
|
|
@objc(doSomethingWithString:)
|
|
func doSomething(_ x: String) { }
|
|
}
|
|
let anotherSelector = #selector(SomeClass.doSomething(_:) as (SomeClass) -> (String) -> Void)
|
|
```
|
|
|
|
<!--
|
|
- test: `selector-expression-with-as`
|
|
|
|
```swifttest
|
|
>> import Foundation
|
|
>> class SomeClass: NSObject {
|
|
>> @objc let property: String
|
|
>> @objc(doSomethingWithInt:)
|
|
>> func doSomething(_ x: Int) {}
|
|
>> init(property: String) {
|
|
>> self.property = property
|
|
>> }
|
|
>> }
|
|
-> extension SomeClass {
|
|
-> @objc(doSomethingWithString:)
|
|
func doSomething(_ x: String) { }
|
|
}
|
|
-> let anotherSelector = #selector(SomeClass.doSomething(_:) as (SomeClass) -> (String) -> Void)
|
|
```
|
|
-->
|
|
|
|
Because a selector is created at compile time, not at runtime,
|
|
the compiler can check that a method or property exists
|
|
and that they're exposed to the Objective-C runtime.
|
|
|
|
> Note: Although the *method name* and the *property name* are expressions,
|
|
> they're never evaluated.
|
|
|
|
For more information about using selectors
|
|
in Swift code that interacts with Objective-C APIs,
|
|
see [Using Objective-C Runtime Features in Swift](https://developer.apple.com/documentation/swift/using_objective_c_runtime_features_in_swift).
|
|
|
|
> Grammar of a selector expression:
|
|
>
|
|
> *selector-expression* → **`#selector`** **`(`** *expression* **`)`** \
|
|
> *selector-expression* → **`#selector`** **`(`** **`getter:`** *expression* **`)`** \
|
|
> *selector-expression* → **`#selector`** **`(`** **`setter:`** *expression* **`)`**
|
|
|
|
<!--
|
|
Note: The parser does allow an arbitrary expression inside #selector(), not
|
|
just a member name. For example, see changes in Swift commit ef60d7289d in
|
|
lib/Sema/CSApply.cpp -- there's explicit code to look through parens and
|
|
optional binding.
|
|
-->
|
|
|
|
### Key-Path String Expression
|
|
|
|
A key-path string expression lets you access the string
|
|
used to refer to a property in Objective-C,
|
|
for use in key-value coding and key-value observing APIs.
|
|
It has the following form:
|
|
|
|
```swift
|
|
#keyPath(<#property name#>)
|
|
```
|
|
|
|
The *property name* must be a reference to a property
|
|
that's available in the Objective-C runtime.
|
|
At compile time, the key-path string expression is replaced by a string literal.
|
|
For example:
|
|
|
|
```swift
|
|
class SomeClass: NSObject {
|
|
@objc var someProperty: Int
|
|
init(someProperty: Int) {
|
|
self.someProperty = someProperty
|
|
}
|
|
}
|
|
|
|
let c = SomeClass(someProperty: 12)
|
|
let keyPath = #keyPath(SomeClass.someProperty)
|
|
|
|
if let value = c.value(forKey: keyPath) {
|
|
print(value)
|
|
}
|
|
// Prints "12".
|
|
```
|
|
|
|
<!--
|
|
- test: `keypath-string-expression`
|
|
|
|
```swifttest
|
|
>> import Foundation
|
|
-> class SomeClass: NSObject {
|
|
-> @objc var someProperty: Int
|
|
init(someProperty: Int) {
|
|
self.someProperty = someProperty
|
|
}
|
|
}
|
|
|
|
-> let c = SomeClass(someProperty: 12)
|
|
-> let keyPath = #keyPath(SomeClass.someProperty)
|
|
|
|
-> if let value = c.value(forKey: keyPath) {
|
|
-> print(value)
|
|
-> }
|
|
<- 12
|
|
```
|
|
-->
|
|
|
|
When you use a key-path string expression within a class,
|
|
you can refer to a property of that class
|
|
by writing just the property name, without the class name.
|
|
|
|
```swift
|
|
extension SomeClass {
|
|
func getSomeKeyPath() -> String {
|
|
return #keyPath(someProperty)
|
|
}
|
|
}
|
|
print(keyPath == c.getSomeKeyPath())
|
|
// Prints "true".
|
|
```
|
|
|
|
<!--
|
|
- test: `keypath-string-expression`
|
|
|
|
```swifttest
|
|
-> extension SomeClass {
|
|
func getSomeKeyPath() -> String {
|
|
return #keyPath(someProperty)
|
|
}
|
|
}
|
|
-> print(keyPath == c.getSomeKeyPath())
|
|
<- true
|
|
```
|
|
-->
|
|
|
|
Because the key path string is created at compile time, not at runtime,
|
|
the compiler can check that the property exists
|
|
and that the property is exposed to the Objective-C runtime.
|
|
|
|
For more information about using key paths
|
|
in Swift code that interacts with Objective-C APIs,
|
|
see [Using Objective-C Runtime Features in Swift](https://developer.apple.com/documentation/swift/using_objective_c_runtime_features_in_swift).
|
|
For information about key-value coding and key-value observing,
|
|
see [Key-Value Coding Programming Guide](https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/KeyValueCoding/index.html#//apple_ref/doc/uid/10000107i)
|
|
and [Key-Value Observing Programming Guide](https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/KeyValueObserving/KeyValueObserving.html#//apple_ref/doc/uid/10000177i).
|
|
|
|
> Note: Although the *property name* is an expression, it's never evaluated.
|
|
|
|
> Grammar of a key-path string expression:
|
|
>
|
|
> *key-path-string-expression* → **`#keyPath`** **`(`** *expression* **`)`**
|
|
|
|
## Postfix Expressions
|
|
|
|
*Postfix expressions* are formed
|
|
by applying a postfix operator or other postfix syntax
|
|
to an expression.
|
|
Syntactically, every primary expression is also a postfix expression.
|
|
|
|
For information about the behavior of these operators,
|
|
see <doc:BasicOperators> and <doc:AdvancedOperators>.
|
|
|
|
For information about the operators provided by the Swift standard library,
|
|
see [Operator Declarations](https://developer.apple.com/documentation/swift/operator_declarations).
|
|
|
|
> Grammar of a postfix expression:
|
|
>
|
|
> *postfix-expression* → *primary-expression* \
|
|
> *postfix-expression* → *postfix-expression* *postfix-operator* \
|
|
> *postfix-expression* → *function-call-expression* \
|
|
> *postfix-expression* → *initializer-expression* \
|
|
> *postfix-expression* → *explicit-member-expression* \
|
|
> *postfix-expression* → *postfix-self-expression* \
|
|
> *postfix-expression* → *subscript-expression* \
|
|
> *postfix-expression* → *forced-value-expression* \
|
|
> *postfix-expression* → *optional-chaining-expression*
|
|
|
|
### Function Call Expression
|
|
|
|
<!--
|
|
TODO: After we rewrite function decls,
|
|
revisit this section to make sure that the names for things match.
|
|
-->
|
|
|
|
A *function call expression* consists of a function name
|
|
followed by a comma-separated list of the function's arguments in parentheses.
|
|
Function call expressions have the following form:
|
|
|
|
```swift
|
|
<#function name#>(<#argument value 1#>, <#argument value 2#>)
|
|
```
|
|
|
|
The *function name* can be any expression whose value is of a function type.
|
|
|
|
If the function definition includes names for its parameters,
|
|
the function call must include names before its argument values,
|
|
separated by a colon (`:`).
|
|
This kind of function call expression has the following form:
|
|
|
|
```swift
|
|
<#function name#>(<#argument name 1#>: <#argument value 1#>, <#argument name 2#>: <#argument value 2#>)
|
|
```
|
|
|
|
A function call expression can include trailing closures
|
|
in the form of closure expressions immediately after the closing parenthesis.
|
|
The trailing closures are understood as arguments to the function,
|
|
added after the last parenthesized argument.
|
|
The first closure expression is unlabeled;
|
|
any additional closure expressions are preceded by their argument labels.
|
|
The example below shows the equivalent version of function calls
|
|
that do and don't use trailing closure syntax:
|
|
|
|
```swift
|
|
// someFunction takes an integer and a closure as its arguments
|
|
someFunction(x: x, f: { $0 == 13 })
|
|
someFunction(x: x) { $0 == 13 }
|
|
|
|
// anotherFunction takes an integer and two closures as its arguments
|
|
anotherFunction(x: x, f: { $0 == 13 }, g: { print(99) })
|
|
anotherFunction(x: x) { $0 == 13 } g: { print(99) }
|
|
```
|
|
|
|
<!--
|
|
- test: `trailing-closure`
|
|
|
|
```swifttest
|
|
>> func someFunction (x: Int, f: (Int) -> Bool) -> Bool {
|
|
>> return f(x)
|
|
>> }
|
|
>> let x = 10
|
|
// someFunction takes an integer and a closure as its arguments
|
|
>> let r0 =
|
|
-> someFunction(x: x, f: { $0 == 13 })
|
|
>> assert(r0 == false)
|
|
>> let r1 =
|
|
-> someFunction(x: x) { $0 == 13 }
|
|
>> assert(r1 == false)
|
|
|
|
>> func anotherFunction(x: Int, f: (Int) -> Bool, g: () -> Void) -> Bool {
|
|
>> g(); return f(x)
|
|
>> }
|
|
// anotherFunction takes an integer and two closures as its arguments
|
|
>> let r2 =
|
|
-> anotherFunction(x: x, f: { $0 == 13 }, g: { print(99) })
|
|
<< 99
|
|
>> assert(r2 == false)
|
|
>> let r3 =
|
|
-> anotherFunction(x: x) { $0 == 13 } g: { print(99) }
|
|
<< 99
|
|
>> assert(r3 == false)
|
|
```
|
|
-->
|
|
|
|
<!--
|
|
Rewrite the above to avoid bare expressions.
|
|
Tracking bug is <rdar://problem/35301593>
|
|
-->
|
|
|
|
If the trailing closure is the function's only argument,
|
|
you can omit the parentheses.
|
|
|
|
```swift
|
|
// someMethod takes a closure as its only argument
|
|
myData.someMethod() { $0 == 13 }
|
|
myData.someMethod { $0 == 13 }
|
|
```
|
|
|
|
<!--
|
|
- test: `no-paren-trailing-closure`
|
|
|
|
```swifttest
|
|
>> class Data {
|
|
>> let data = 10
|
|
>> func someMethod(f: (Int) -> Bool) -> Bool {
|
|
>> return f(self.data)
|
|
>> }
|
|
>> }
|
|
>> let myData = Data()
|
|
// someMethod takes a closure as its only argument
|
|
>> let r0 =
|
|
-> myData.someMethod() { $0 == 13 }
|
|
>> assert(r0 == false)
|
|
>> let r1 =
|
|
-> myData.someMethod { $0 == 13 }
|
|
>> assert(r1 == false)
|
|
```
|
|
-->
|
|
|
|
<!--
|
|
Rewrite the above to avoid bare expressions.
|
|
Tracking bug is <rdar://problem/35301593>
|
|
-->
|
|
|
|
To include the trailing closures in the arguments,
|
|
the compiler examines the function's parameters from left to right as follows:
|
|
|
|
| Trailing Closure | Parameter | Action |
|
|
| ---------------- | --------- | ------ |
|
|
| Labeled | Labeled | If the labels are the same, the closure matches the parameter; otherwise, the parameter is skipped. |
|
|
| Labeled | Unlabeled | The parameter is skipped. |
|
|
| Unlabeled | Labeled or unlabeled | If the parameter structurally resembles a function type, as defined below, the closure matches the parameter; otherwise, the parameter is skipped. |
|
|
|
|
The trailing closure is passed as the argument for the parameter that it matches.
|
|
Parameters that were skipped during the scanning process
|
|
don't have an argument passed to them ---
|
|
for example, they can use a default parameter.
|
|
After finding a match, scanning continues
|
|
with the next trailing closure and the next parameter.
|
|
At the end of the matching process,
|
|
all trailing closures must have a match.
|
|
|
|
A parameter *structurally resembles* a function type
|
|
if the parameter isn't an in-out parameter,
|
|
and the parameter is one of the following:
|
|
|
|
- A parameter whose type is a function type,
|
|
like `(Bool) -> Int`
|
|
- An autoclosure parameter
|
|
whose wrapped expression's type is a function type,
|
|
like `@autoclosure () -> ((Bool) -> Int)`
|
|
- A variadic parameter
|
|
whose array element type is a function type,
|
|
like `((Bool) -> Int)...`
|
|
- A parameter whose type is wrapped in one or more layers of optional,
|
|
like `Optional<(Bool) -> Int>`
|
|
- A parameter whose type combines these allowed types,
|
|
like `(Optional<(Bool) -> Int>)...`
|
|
|
|
When a trailing closure is matched to a parameter
|
|
whose type structurally resembles a function type, but isn't a function,
|
|
the closure is wrapped as needed.
|
|
For example, if the parameter's type is an optional type,
|
|
the closure is wrapped in `Optional` automatically.
|
|
|
|
<!--
|
|
- test: `when-can-you-use-trailing-closure`
|
|
|
|
```swifttest
|
|
// These tests match the example types given above
|
|
// when describing what "structurally resembles" a function type.
|
|
|
|
>> func f1(x: Int, y: (Bool)->Int) { print(x + y(true)) }
|
|
>> f1(x: 10) { $0 ? 1 : 100 }
|
|
<< 11
|
|
>> func f2(x: Int, y: @autoclosure ()->((Bool)->Int)) { print(x + y()(false)) }
|
|
>> f2(x: 20) { $0 ? 2 : 200 }
|
|
<< 220
|
|
>> func f3(x: Int, y: ((Bool)->Int)...) { print(x + y[0](true)) }
|
|
>> f3(x: 30) { $0 ? 3 : 300}
|
|
<< 33
|
|
>> func f4(x: Int, y: Optional<(Bool)->Int>) { print(x + y!(false)) }
|
|
>> f4(x: 40) { $0 ? 4 : 400 }
|
|
<< 440
|
|
>> func f5(x: Int, y: (Optional<(Bool) -> Int>)...) { print(x + y[0]!(true)) }
|
|
>> f5(x: 50) { $0 ? 5 : 500 }
|
|
<< 55
|
|
```
|
|
-->
|
|
|
|
To ease migration of code from versions of Swift prior to 5.3 ---
|
|
which performed this matching from right to left ---
|
|
the compiler checks both the left-to-right and right-to-left orderings.
|
|
If the scan directions produce different results,
|
|
the old right-to-left ordering is used
|
|
and the compiler generates a warning.
|
|
A future version of Swift will always use the left-to-right ordering.
|
|
|
|
```swift
|
|
typealias Callback = (Int) -> Int
|
|
func someFunction(firstClosure: Callback? = nil,
|
|
secondClosure: Callback? = nil) {
|
|
let first = firstClosure?(10)
|
|
let second = secondClosure?(20)
|
|
print(first ?? "-", second ?? "-")
|
|
}
|
|
|
|
someFunction() // Prints "- -"
|
|
someFunction { return $0 + 100 } // Ambiguous
|
|
someFunction { return $0 } secondClosure: { return $0 } // Prints "10 20"
|
|
```
|
|
|
|
<!--
|
|
- test: `trailing-closure-scanning-direction`
|
|
|
|
```swifttest
|
|
-> typealias Callback = (Int) -> Int
|
|
-> func someFunction(firstClosure: Callback? = nil,
|
|
secondClosure: Callback? = nil) {
|
|
let first = firstClosure?(10)
|
|
let second = secondClosure?(20)
|
|
print(first ?? "-", second ?? "-")
|
|
}
|
|
|
|
-> someFunction() // Prints "- -"
|
|
<< - -
|
|
-> someFunction { return $0 + 100 } // Ambiguous
|
|
<< - 120
|
|
!$ warning: backward matching of the unlabeled trailing closure is deprecated; label the argument with 'secondClosure' to suppress this warning
|
|
!! someFunction { return $0 + 100 } // Ambiguous
|
|
!! ^
|
|
!! (secondClosure: )
|
|
!$ note: 'someFunction(firstClosure:secondClosure:)' declared here
|
|
!! func someFunction(firstClosure: Callback? = nil,
|
|
!! ^
|
|
-> someFunction { return $0 } secondClosure: { return $0 } // Prints "10 20"
|
|
<< 10 20
|
|
```
|
|
-->
|
|
|
|
In the example above,
|
|
the function call marked "Ambiguous"
|
|
prints "- 120" and produces a compiler warning on Swift 5.3.
|
|
A future version of Swift will print “110 -”.
|
|
|
|
<!--
|
|
Smart quotes on the line above are needed
|
|
because the regex heuristics gets the close quote wrong.
|
|
-->
|
|
|
|
A class, structure, or enumeration type
|
|
can enable syntactic sugar for function call syntax
|
|
by declaring one of several methods,
|
|
as described in <doc:Declarations#Methods-with-Special-Names>.
|
|
|
|
#### Implicit Conversion to a Pointer Type
|
|
|
|
In a function call expression,
|
|
if the argument and parameter have a different type,
|
|
the compiler tries to make their types match
|
|
by applying one of the implicit conversions in the following list:
|
|
|
|
- `inout SomeType` can become
|
|
`UnsafePointer<SomeType>` or `UnsafeMutablePointer<SomeType>`
|
|
- `inout Array<SomeType>` can become
|
|
`UnsafePointer<SomeType>` or `UnsafeMutablePointer<SomeType>`
|
|
- `Array<SomeType>` can become `UnsafePointer<SomeType>`
|
|
- `String` can become `UnsafePointer<CChar>`
|
|
|
|
The following two function calls are equivalent:
|
|
|
|
```swift
|
|
func unsafeFunction(pointer: UnsafePointer<Int>) {
|
|
// ...
|
|
}
|
|
var myNumber = 1234
|
|
|
|
unsafeFunction(pointer: &myNumber)
|
|
withUnsafePointer(to: myNumber) { unsafeFunction(pointer: $0) }
|
|
```
|
|
|
|
<!--
|
|
- test: `inout-unsafe-pointer`
|
|
|
|
```swifttest
|
|
-> func unsafeFunction(pointer: UnsafePointer<Int>) {
|
|
-> // ...
|
|
>> print(pointer.pointee)
|
|
-> }
|
|
-> var myNumber = 1234
|
|
|
|
-> unsafeFunction(pointer: &myNumber)
|
|
-> withUnsafePointer(to: myNumber) { unsafeFunction(pointer: $0) }
|
|
<< 1234
|
|
<< 1234
|
|
```
|
|
-->
|
|
|
|
A pointer that's created by these implicit conversions
|
|
is valid only for the duration of the function call.
|
|
To avoid undefined behavior,
|
|
ensure that your code
|
|
never persists the pointer after the function call ends.
|
|
|
|
> Note: When implicitly converting an array to an unsafe pointer,
|
|
> Swift ensures that the array's storage is contiguous
|
|
> by converting or copying the array as needed.
|
|
> For example, you can use this syntax
|
|
> with an array that was bridged to `Array`
|
|
> from an `NSArray` subclass that makes no API contract about its storage.
|
|
> If you need to guarantee that the array's storage is already contiguous,
|
|
> so the implicit conversion never needs to do this work,
|
|
> use `ContiguousArray` instead of `Array`.
|
|
|
|
Using `&` instead of an explicit function like `withUnsafePointer(to:)`
|
|
can help make calls to low-level C functions more readable,
|
|
especially when the function takes several pointer arguments.
|
|
However, when calling functions from other Swift code,
|
|
avoid using `&` instead of using the unsafe APIs explicitly.
|
|
|
|
<!--
|
|
- test: `implicit-conversion-to-pointer`
|
|
|
|
```swifttest
|
|
>> import Foundation
|
|
>> func takesUnsafePointer(p: UnsafePointer<Int>) { }
|
|
>> func takesUnsafeMutablePointer(p: UnsafeMutablePointer<Int>) { }
|
|
>> func takesUnsafePointerCChar(p: UnsafePointer<CChar>) { }
|
|
>> func takesUnsafeMutablePointerCChar(p: UnsafeMutablePointer<CChar>) { }
|
|
>> var n = 12
|
|
>> var array = [1, 2, 3]
|
|
>> var nsarray: NSArray = [10, 20, 30]
|
|
>> var bridgedNSArray = nsarray as! Array<Int>
|
|
>> var string = "Hello"
|
|
|
|
// bullet 1
|
|
>> takesUnsafePointer(p: &n)
|
|
>> takesUnsafeMutablePointer(p: &n)
|
|
|
|
// bullet 2
|
|
>> takesUnsafePointer(p: &array)
|
|
>> takesUnsafeMutablePointer(p: &array)
|
|
>> takesUnsafePointer(p: &bridgedNSArray)
|
|
>> takesUnsafeMutablePointer(p: &bridgedNSArray)
|
|
|
|
// bullet 3
|
|
>> takesUnsafePointer(p: array)
|
|
>> takesUnsafePointer(p: bridgedNSArray)
|
|
|
|
// bullet 4
|
|
>> takesUnsafePointerCChar(p: string)
|
|
|
|
// invalid conversions
|
|
>> takesUnsafeMutablePointer(p: array)
|
|
!$ error: cannot convert value of type '[Int]' to expected argument type 'UnsafeMutablePointer<Int>'
|
|
!! takesUnsafeMutablePointer(p: array)
|
|
!! ^
|
|
>> takesUnsafeMutablePointerCChar(p: string)
|
|
!$ error: cannot convert value of type 'String' to expected argument type 'UnsafeMutablePointer<CChar>' (aka 'UnsafeMutablePointer<Int8>')
|
|
!! takesUnsafeMutablePointerCChar(p: string)
|
|
!! ^
|
|
```
|
|
-->
|
|
|
|
> Grammar of a function call expression:
|
|
>
|
|
> *function-call-expression* → *postfix-expression* *function-call-argument-clause* \
|
|
> *function-call-expression* → *postfix-expression* *function-call-argument-clause*_?_ *trailing-closures*
|
|
>
|
|
> *function-call-argument-clause* → **`(`** **`)`** | **`(`** *function-call-argument-list* **`)`** \
|
|
> *function-call-argument-list* → *function-call-argument* | *function-call-argument* **`,`** *function-call-argument-list* \
|
|
> *function-call-argument* → *expression* | *identifier* **`:`** *expression* \
|
|
> *function-call-argument* → *operator* | *identifier* **`:`** *operator*
|
|
>
|
|
> *trailing-closures* → *closure-expression* *labeled-trailing-closures*_?_ \
|
|
> *labeled-trailing-closures* → *labeled-trailing-closure* *labeled-trailing-closures*_?_ \
|
|
> *labeled-trailing-closure* → *identifier* **`:`** *closure-expression*
|
|
|
|
### Initializer Expression
|
|
|
|
An *initializer expression* provides access
|
|
to a type's initializer.
|
|
It has the following form:
|
|
|
|
```swift
|
|
<#expression#>.init(<#initializer arguments#>)
|
|
```
|
|
|
|
You use the initializer expression in a function call expression
|
|
to initialize a new instance of a type.
|
|
You also use an initializer expression
|
|
to delegate to the initializer of a superclass.
|
|
|
|
```swift
|
|
class SomeSubClass: SomeSuperClass {
|
|
override init() {
|
|
// subclass initialization goes here
|
|
super.init()
|
|
}
|
|
}
|
|
```
|
|
|
|
<!--
|
|
- test: `init-call-superclass`
|
|
|
|
```swifttest
|
|
>> class SomeSuperClass { }
|
|
-> class SomeSubClass: SomeSuperClass {
|
|
-> override init() {
|
|
-> // subclass initialization goes here
|
|
-> super.init()
|
|
-> }
|
|
-> }
|
|
```
|
|
-->
|
|
|
|
Like a function, an initializer can be used as a value.
|
|
For example:
|
|
|
|
```swift
|
|
// Type annotation is required because String has multiple initializers.
|
|
let initializer: (Int) -> String = String.init
|
|
let oneTwoThree = [1, 2, 3].map(initializer).reduce("", +)
|
|
print(oneTwoThree)
|
|
// Prints "123".
|
|
```
|
|
|
|
<!--
|
|
- test: `init-as-value`
|
|
|
|
```swifttest
|
|
// Type annotation is required because String has multiple initializers.
|
|
-> let initializer: (Int) -> String = String.init
|
|
-> let oneTwoThree = [1, 2, 3].map(initializer).reduce("", +)
|
|
-> print(oneTwoThree)
|
|
<- 123
|
|
```
|
|
-->
|
|
|
|
If you specify a type by name,
|
|
you can access the type's initializer without using an initializer expression.
|
|
In all other cases, you must use an initializer expression.
|
|
|
|
```swift
|
|
let s1 = SomeType.init(data: 3) // Valid
|
|
let s2 = SomeType(data: 1) // Also valid
|
|
|
|
let s3 = type(of: someValue).init(data: 7) // Valid
|
|
let s4 = type(of: someValue)(data: 5) // Error
|
|
```
|
|
|
|
<!--
|
|
- test: `explicit-implicit-init`
|
|
|
|
```swifttest
|
|
>> struct SomeType {
|
|
>> let data: Int
|
|
>> }
|
|
-> let s1 = SomeType.init(data: 3) // Valid
|
|
-> let s2 = SomeType(data: 1) // Also valid
|
|
|
|
>> let someValue = s1
|
|
-> let s3 = type(of: someValue).init(data: 7) // Valid
|
|
-> let s4 = type(of: someValue)(data: 5) // Error
|
|
!$ error: initializing from a metatype value must reference 'init' explicitly
|
|
!! let s4 = type(of: someValue)(data: 5) // Error
|
|
!! ^
|
|
!! .init
|
|
```
|
|
-->
|
|
|
|
> Grammar of an initializer expression:
|
|
>
|
|
> *initializer-expression* → *postfix-expression* **`.`** **`init`** \
|
|
> *initializer-expression* → *postfix-expression* **`.`** **`init`** **`(`** *argument-names* **`)`**
|
|
|
|
### Explicit Member Expression
|
|
|
|
An *explicit member expression* allows access
|
|
to the members of a named type, a tuple, or a module.
|
|
It consists of a period (`.`) between the item
|
|
and the identifier of its member.
|
|
|
|
```swift
|
|
<#expression#>.<#member name#>
|
|
```
|
|
|
|
The members of a named type are named
|
|
as part of the type's declaration or extension.
|
|
For example:
|
|
|
|
```swift
|
|
class SomeClass {
|
|
var someProperty = 42
|
|
}
|
|
let c = SomeClass()
|
|
let y = c.someProperty // Member access
|
|
```
|
|
|
|
<!--
|
|
- test: `explicitMemberExpression`
|
|
|
|
```swifttest
|
|
-> class SomeClass {
|
|
var someProperty = 42
|
|
}
|
|
-> let c = SomeClass()
|
|
-> let y = c.someProperty // Member access
|
|
```
|
|
-->
|
|
|
|
The members of a tuple
|
|
are implicitly named using integers in the order they appear,
|
|
starting from zero.
|
|
For example:
|
|
|
|
```swift
|
|
var t = (10, 20, 30)
|
|
t.0 = t.1
|
|
// Now t is (20, 20, 30)
|
|
```
|
|
|
|
<!--
|
|
- test: `explicit-member-expression`
|
|
|
|
```swifttest
|
|
-> var t = (10, 20, 30)
|
|
-> t.0 = t.1
|
|
-> // Now t is (20, 20, 30)
|
|
```
|
|
-->
|
|
|
|
The members of a module access
|
|
the top-level declarations of that module.
|
|
|
|
Types declared with the `dynamicMemberLookup` attribute
|
|
include members that are looked up at runtime,
|
|
as described in <doc:Attributes>.
|
|
|
|
To distinguish between methods or initializers
|
|
whose names differ only by the names of their arguments,
|
|
include the argument names in parentheses,
|
|
with each argument name followed by a colon (`:`).
|
|
Write an underscore (`_`) for an argument with no name.
|
|
To distinguish between overloaded methods,
|
|
use a type annotation.
|
|
For example:
|
|
|
|
```swift
|
|
class SomeClass {
|
|
func someMethod(x: Int, y: Int) {}
|
|
func someMethod(x: Int, z: Int) {}
|
|
func overloadedMethod(x: Int, y: Int) {}
|
|
func overloadedMethod(x: Int, y: Bool) {}
|
|
}
|
|
let instance = SomeClass()
|
|
|
|
let a = instance.someMethod // Ambiguous
|
|
let b = instance.someMethod(x:y:) // Unambiguous
|
|
|
|
let d = instance.overloadedMethod // Ambiguous
|
|
let d = instance.overloadedMethod(x:y:) // Still ambiguous
|
|
let d: (Int, Bool) -> Void = instance.overloadedMethod(x:y:) // Unambiguous
|
|
```
|
|
|
|
<!--
|
|
- test: `function-with-argument-names`
|
|
|
|
```swifttest
|
|
-> class SomeClass {
|
|
func someMethod(x: Int, y: Int) {}
|
|
func someMethod(x: Int, z: Int) {}
|
|
func overloadedMethod(x: Int, y: Int) {}
|
|
func overloadedMethod(x: Int, y: Bool) {}
|
|
}
|
|
-> let instance = SomeClass()
|
|
|
|
-> let a = instance.someMethod // Ambiguous
|
|
!$ error: ambiguous use of 'someMethod'
|
|
!! let a = instance.someMethod // Ambiguous
|
|
!! ^
|
|
!$ note: found this candidate
|
|
!! func someMethod(x: Int, y: Int) {}
|
|
!! ^
|
|
!$ note: found this candidate
|
|
!! func someMethod(x: Int, z: Int) {}
|
|
!! ^
|
|
-> let b = instance.someMethod(x:y:) // Unambiguous
|
|
|
|
-> let d = instance.overloadedMethod // Ambiguous
|
|
!$ error: ambiguous use of 'overloadedMethod(x:y:)'
|
|
!! let d = instance.overloadedMethod // Ambiguous
|
|
!! ^
|
|
!$ note: found this candidate
|
|
!! func overloadedMethod(x: Int, y: Int) {}
|
|
!! ^
|
|
!$ note: found this candidate
|
|
!! func overloadedMethod(x: Int, y: Bool) {}
|
|
!! ^
|
|
-> let d = instance.overloadedMethod(x:y:) // Still ambiguous
|
|
!$ error: ambiguous use of 'overloadedMethod(x:y:)'
|
|
!! let d = instance.overloadedMethod(x:y:) // Still ambiguous
|
|
!! ^
|
|
!$ note: found this candidate
|
|
!! func overloadedMethod(x: Int, y: Int) {}
|
|
!! ^
|
|
!$ note: found this candidate
|
|
!! func overloadedMethod(x: Int, y: Bool) {}
|
|
!! ^
|
|
-> let d: (Int, Bool) -> Void = instance.overloadedMethod(x:y:) // Unambiguous
|
|
```
|
|
-->
|
|
|
|
If a period appears at the beginning of a line,
|
|
it's understood as part of an explicit member expression,
|
|
not as an implicit member expression.
|
|
For example, the following listing shows chained method calls
|
|
split over several lines:
|
|
|
|
```swift
|
|
let x = [10, 3, 20, 15, 4]
|
|
.sorted()
|
|
.filter { $0 > 5 }
|
|
.map { $0 * 100 }
|
|
```
|
|
|
|
<!--
|
|
- test: `period-at-start-of-line`
|
|
|
|
```swifttest
|
|
-> let x = [10, 3, 20, 15, 4]
|
|
-> .sorted()
|
|
-> .filter { $0 > 5 }
|
|
-> .map { $0 * 100 }
|
|
>> print(x)
|
|
<< [1000, 1500, 2000]
|
|
```
|
|
-->
|
|
|
|
You can combine this multiline chained syntax
|
|
with compiler control statements
|
|
to control when each method is called.
|
|
For example,
|
|
the following code uses a different filtering rule on iOS:
|
|
|
|
```swift
|
|
let numbers = [10, 20, 33, 43, 50]
|
|
#if os(iOS)
|
|
.filter { $0 < 40 }
|
|
#else
|
|
.filter { $0 > 25 }
|
|
#endif
|
|
```
|
|
|
|
<!--
|
|
- test: `pound-if-inside-postfix-expression`
|
|
|
|
```swifttest
|
|
-> let numbers = [10, 20, 33, 43, 50]
|
|
#if os(iOS)
|
|
.filter { $0 < 40 }
|
|
#else
|
|
.filter { $0 > 25 }
|
|
#endif
|
|
>> print(numbers)
|
|
<< [33, 43, 50]
|
|
```
|
|
-->
|
|
|
|
Between `#if`, `#endif`, and other compilation directives,
|
|
the conditional compilation block can contain
|
|
an implicit member expression
|
|
followed by zero or more postfixes,
|
|
to form a postfix expression.
|
|
It can also contain
|
|
another conditional compilation block,
|
|
or a combination of these expressions and blocks.
|
|
|
|
You can use this syntax anywhere that you can write
|
|
an explicit member expression,
|
|
not just in top-level code.
|
|
|
|
In the conditional compilation block,
|
|
the branch for the `#if` compilation directive
|
|
must contain at least one expression.
|
|
The other branches can be empty.
|
|
|
|
<!--
|
|
- test: `pound-if-empty-if-not-allowed`
|
|
|
|
```swifttest
|
|
>> let numbers = [10, 20, 33, 43, 50]
|
|
>> #if os(iOS)
|
|
>> #else
|
|
>> .filter { $0 > 25 }
|
|
>> #endif
|
|
!$ error: reference to member 'filter' cannot be resolved without a contextual type
|
|
!! .filter { $0 > 25 }
|
|
!! ~^~~~~~
|
|
```
|
|
-->
|
|
|
|
<!--
|
|
- test: `pound-if-else-can-be-empty`
|
|
|
|
```swifttest
|
|
>> let numbers = [10, 20, 33, 43, 50]
|
|
>> #if os(iOS)
|
|
>> .filter { $0 > 25 }
|
|
>> #else
|
|
>> #endif
|
|
>> print(numbers)
|
|
<< [10, 20, 33, 43, 50]
|
|
```
|
|
-->
|
|
|
|
<!--
|
|
- test: `pound-if-cant-use-binary-operators`
|
|
|
|
```swifttest
|
|
>> let s = "some string"
|
|
>> #if os(iOS)
|
|
>> + " on iOS"
|
|
>> #endif
|
|
!$ error: unary operator cannot be separated from its operand
|
|
!! + " on iOS"
|
|
!! ^~
|
|
!!-
|
|
```
|
|
-->
|
|
|
|
> Grammar of an explicit member expression:
|
|
>
|
|
> *explicit-member-expression* → *postfix-expression* **`.`** *decimal-digits* \
|
|
> *explicit-member-expression* → *postfix-expression* **`.`** *identifier* *generic-argument-clause*_?_ \
|
|
> *explicit-member-expression* → *postfix-expression* **`.`** *identifier* **`(`** *argument-names* **`)`** \
|
|
> *explicit-member-expression* → *postfix-expression* *conditional-compilation-block*
|
|
>
|
|
> *argument-names* → *argument-name* *argument-names*_?_ \
|
|
> *argument-name* → *identifier* **`:`**
|
|
|
|
<!--
|
|
The grammar for method-name doesn't include the following:
|
|
method-name -> identifier argument-names-OPT
|
|
because the "postfix-expression . identifier" line above already covers that case.
|
|
-->
|
|
|
|
<!--
|
|
See grammar for initializer-expression for the related "argument name" production there.
|
|
-->
|
|
|
|
### Postfix Self Expression
|
|
|
|
A postfix `self` expression consists of an expression or the name of a type,
|
|
immediately followed by `.self`. It has the following forms:
|
|
|
|
```swift
|
|
<#expression#>.self
|
|
<#type#>.self
|
|
```
|
|
|
|
The first form evaluates to the value of the *expression*.
|
|
For example, `x.self` evaluates to `x`.
|
|
|
|
The second form evaluates to the value of the *type*. Use this form
|
|
to access a type as a value. For example,
|
|
because `SomeClass.self` evaluates to the `SomeClass` type itself,
|
|
you can pass it to a function or method that accepts a type-level argument.
|
|
|
|
> Grammar of a postfix self expression:
|
|
>
|
|
> *postfix-self-expression* → *postfix-expression* **`.`** **`self`**
|
|
|
|
### Subscript Expression
|
|
|
|
A *subscript expression* provides subscript access
|
|
using the getter and setter
|
|
of the corresponding subscript declaration.
|
|
It has the following form:
|
|
|
|
```swift
|
|
<#expression#>[<#index expressions#>]
|
|
```
|
|
|
|
To evaluate the value of a subscript expression,
|
|
the subscript getter for the *expression*'s type is called
|
|
with the *index expressions* passed as the subscript parameters.
|
|
To set its value,
|
|
the subscript setter is called in the same way.
|
|
|
|
<!--
|
|
TR: Confirm that indexing on
|
|
a comma-separated list of expressions
|
|
is intentional, not just a side effect.
|
|
I see this working, for example:
|
|
(swift) class Test {
|
|
subscript(a: Int, b: Int) -> Int { return 12 }
|
|
}
|
|
(swift) var t = Test()
|
|
// t : Test = <Test instance>
|
|
(swift) t[1, 2]
|
|
// r0 : Int = 12
|
|
-->
|
|
|
|
For information about subscript declarations,
|
|
see <doc:Declarations#Protocol-Subscript-Declaration>.
|
|
|
|
> Grammar of a subscript expression:
|
|
>
|
|
> *subscript-expression* → *postfix-expression* **`[`** *function-call-argument-list* **`]`**
|
|
|
|
<!--
|
|
- test: `subscripts-can-take-operators`
|
|
|
|
```swifttest
|
|
>> struct S {
|
|
let x: Int
|
|
let y: Int
|
|
subscript(operation: (Int, Int) -> Int) -> Int {
|
|
return operation(x, y)
|
|
}
|
|
}
|
|
>> let s = S(x: 10, y: 20)
|
|
>> assert(s[+] == 30)
|
|
```
|
|
-->
|
|
|
|
### Forced-Value Expression
|
|
|
|
A *forced-value expression* unwraps an optional value
|
|
that you are certain isn't `nil`.
|
|
It has the following form:
|
|
|
|
```swift
|
|
<#expression#>!
|
|
```
|
|
|
|
If the value of the *expression* isn't `nil`,
|
|
the optional value is unwrapped
|
|
and returned with the corresponding non-optional type.
|
|
Otherwise, a runtime error is raised.
|
|
|
|
The unwrapped value of a forced-value expression can be modified,
|
|
either by mutating the value itself,
|
|
or by assigning to one of the value's members.
|
|
For example:
|
|
|
|
```swift
|
|
var x: Int? = 0
|
|
x! += 1
|
|
// x is now 1
|
|
|
|
var someDictionary = ["a": [1, 2, 3], "b": [10, 20]]
|
|
someDictionary["a"]![0] = 100
|
|
// someDictionary is now ["a": [100, 2, 3], "b": [10, 20]]
|
|
```
|
|
|
|
<!--
|
|
- test: `optional-as-lvalue`
|
|
|
|
```swifttest
|
|
-> var x: Int? = 0
|
|
-> x! += 1
|
|
/> x is now \(x!)
|
|
</ x is now 1
|
|
|
|
-> var someDictionary = ["a": [1, 2, 3], "b": [10, 20]]
|
|
-> someDictionary["a"]![0] = 100
|
|
/> someDictionary is now \(someDictionary)
|
|
</ someDictionary is now ["a": [100, 2, 3], "b": [10, 20]]
|
|
```
|
|
-->
|
|
|
|
> Grammar of a forced-value expression:
|
|
>
|
|
> *forced-value-expression* → *postfix-expression* **`!`**
|
|
|
|
### Optional-Chaining Expression
|
|
|
|
An *optional-chaining expression* provides a simplified syntax
|
|
for using optional values in postfix expressions.
|
|
It has the following form:
|
|
|
|
```swift
|
|
<#expression#>?
|
|
```
|
|
|
|
The postfix `?` operator makes an optional-chaining expression
|
|
from an expression without changing the expression's value.
|
|
|
|
Optional-chaining expressions must appear within a postfix expression,
|
|
and they cause the postfix expression to be evaluated in a special way.
|
|
If the value of the optional-chaining expression is `nil`,
|
|
all of the other operations in the postfix expression are ignored
|
|
and the entire postfix expression evaluates to `nil`.
|
|
If the value of the optional-chaining expression isn't `nil`,
|
|
the value of the optional-chaining expression is unwrapped
|
|
and used to evaluate the rest of the postfix expression.
|
|
In either case,
|
|
the value of the postfix expression is still of an optional type.
|
|
|
|
If a postfix expression that contains an optional-chaining expression
|
|
is nested inside other postfix expressions,
|
|
only the outermost expression returns an optional type.
|
|
In the example below,
|
|
when `c` isn't `nil`,
|
|
its value is unwrapped and used to evaluate `.property`,
|
|
the value of which is used to evaluate `.performAction()`.
|
|
The entire expression `c?.property.performAction()`
|
|
has a value of an optional type.
|
|
|
|
```swift
|
|
var c: SomeClass?
|
|
var result: Bool? = c?.property.performAction()
|
|
```
|
|
|
|
<!--
|
|
- test: `optional-chaining`
|
|
|
|
```swifttest
|
|
>> class OtherClass { func performAction() -> Bool {return true} }
|
|
>> class SomeClass { var property: OtherClass = OtherClass() }
|
|
-> var c: SomeClass?
|
|
-> var result: Bool? = c?.property.performAction()
|
|
>> assert(result == nil)
|
|
```
|
|
-->
|
|
|
|
The following example shows the behavior
|
|
of the example above
|
|
without using optional chaining.
|
|
|
|
```swift
|
|
var result: Bool?
|
|
if let unwrappedC = c {
|
|
result = unwrappedC.property.performAction()
|
|
}
|
|
```
|
|
|
|
<!--
|
|
- test: `optional-chaining-alt`
|
|
|
|
```swifttest
|
|
>> class OtherClass { func performAction() -> Bool {return true} }
|
|
>> class SomeClass { var property: OtherClass = OtherClass() }
|
|
>> var c: SomeClass?
|
|
-> var result: Bool?
|
|
-> if let unwrappedC = c {
|
|
result = unwrappedC.property.performAction()
|
|
}
|
|
```
|
|
-->
|
|
|
|
The unwrapped value of an optional-chaining expression can be modified,
|
|
either by mutating the value itself,
|
|
or by assigning to one of the value's members.
|
|
If the value of the optional-chaining expression is `nil`,
|
|
the expression on the right-hand side of the assignment operator
|
|
isn't evaluated.
|
|
For example:
|
|
|
|
```swift
|
|
func someFunctionWithSideEffects() -> Int {
|
|
return 42 // No actual side effects.
|
|
}
|
|
var someDictionary = ["a": [1, 2, 3], "b": [10, 20]]
|
|
|
|
someDictionary["not here"]?[0] = someFunctionWithSideEffects()
|
|
// someFunctionWithSideEffects isn't evaluated
|
|
// someDictionary is still ["a": [1, 2, 3], "b": [10, 20]]
|
|
|
|
someDictionary["a"]?[0] = someFunctionWithSideEffects()
|
|
// someFunctionWithSideEffects is evaluated and returns 42
|
|
// someDictionary is now ["a": [42, 2, 3], "b": [10, 20]]
|
|
```
|
|
|
|
<!--
|
|
- test: `optional-chaining-as-lvalue`
|
|
|
|
```swifttest
|
|
-> func someFunctionWithSideEffects() -> Int {
|
|
return 42 // No actual side effects.
|
|
}
|
|
-> var someDictionary = ["a": [1, 2, 3], "b": [10, 20]]
|
|
|
|
-> someDictionary["not here"]?[0] = someFunctionWithSideEffects()
|
|
// someFunctionWithSideEffects isn't evaluated
|
|
/> someDictionary is still \(someDictionary)
|
|
</ someDictionary is still ["a": [1, 2, 3], "b": [10, 20]]
|
|
|
|
-> someDictionary["a"]?[0] = someFunctionWithSideEffects()
|
|
/> someFunctionWithSideEffects is evaluated and returns \(someFunctionWithSideEffects())
|
|
</ someFunctionWithSideEffects is evaluated and returns 42
|
|
/> someDictionary is now \(someDictionary)
|
|
</ someDictionary is now ["a": [42, 2, 3], "b": [10, 20]]
|
|
```
|
|
-->
|
|
|
|
> Grammar of an optional-chaining expression:
|
|
>
|
|
> *optional-chaining-expression* → *postfix-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
|
|
-->
|