Files
gh-kylehughes-the-unofficia…/skills/programming-swift/LanguageGuide/Closures.md
2025-11-30 08:36:15 +08:00

1345 lines
42 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Closures
Group code that executes together, without creating a named function.
*Closures* are self-contained blocks of functionality
that can be passed around and used in your code.
Closures in Swift are similar
to closures, anonymous functions, lambdas, and blocks
in other programming languages.
Closures can capture and store references to any constants and variables
from the context in which they're defined.
This is known as *closing over* those constants and variables.
Swift handles all of the memory management of capturing for you.
> Note: Don't worry if you aren't familiar with the concept of capturing.
> It's explained in detail below in <doc:Closures#Capturing-Values>.
Global and nested functions, as introduced in <doc:Functions>,
are actually special cases of closures.
Closures take one of three forms:
- Global functions are closures that have a name
and don't capture any values.
- Nested functions are closures that have a name
and can capture values from their enclosing function.
- Closure expressions are unnamed closures written in a lightweight syntax
that can capture values from their surrounding context.
Swift's closure expressions have a clean, clear style,
with optimizations that encourage brief, clutter-free syntax in common scenarios.
These optimizations include:
- Inferring parameter and return value types from context
- Implicit returns from single-expression closures
- Shorthand argument names
- Trailing closure syntax
## Closure Expressions
Nested functions, as introduced in <doc:Functions#Nested-Functions>,
are a convenient means of naming and defining self-contained blocks of code
as part of a larger function.
However, it's sometimes useful to write shorter versions of function-like constructs
without a full declaration and name.
This is particularly true when you work with functions or methods that take functions
as one or more of their arguments.
*Closure expressions* are a way to write inline closures in a brief, focused syntax.
Closure expressions provide several syntax optimizations
for writing closures in a shortened form without loss of clarity or intent.
The closure expression examples below illustrate these optimizations
by refining a single example of the `sorted(by:)` method over several iterations,
each of which expresses the same functionality in a more succinct way.
### The Sorted Method
Swift's standard library provides a method called `sorted(by:)`,
which sorts an array of values of a known type,
based on the output of a sorting closure that you provide.
Once it completes the sorting process,
the `sorted(by:)` method returns a new array of the same type and size as the old one,
with its elements in the correct sorted order.
The original array isn't modified by the `sorted(by:)` method.
The closure expression examples below use the `sorted(by:)` method
to sort an array of `String` values in reverse alphabetical order.
Here's the initial array to be sorted:
```swift
let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
```
<!--
- test: `closureSyntax`
```swifttest
-> let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
```
-->
The `sorted(by:)` method accepts a closure that takes two arguments
of the same type as the array's contents,
and returns a `Bool` value to say whether the first value should appear
before or after the second value once the values are sorted.
The sorting closure needs to return `true`
if the first value should appear *before* the second value,
and `false` otherwise.
This example is sorting an array of `String` values,
and so the sorting closure needs to be a function of type `(String, String) -> Bool`.
One way to provide the sorting closure is to write a normal function of the correct type,
and to pass it in as an argument to the `sorted(by:)` method:
```swift
func backward(_ s1: String, _ s2: String) -> Bool {
return s1 > s2
}
var reversedNames = names.sorted(by: backward)
// reversedNames is equal to ["Ewa", "Daniella", "Chris", "Barry", "Alex"]
```
<!--
- test: `closureSyntax`
```swifttest
-> func backward(_ s1: String, _ s2: String) -> Bool {
return s1 > s2
}
-> var reversedNames = names.sorted(by: backward)
/> reversedNames is equal to \(reversedNames)
</ reversedNames is equal to ["Ewa", "Daniella", "Chris", "Barry", "Alex"]
```
-->
If the first string (`s1`) is greater than the second string (`s2`),
the `backward(_:_:)` function will return `true`,
indicating that `s1` should appear before `s2` in the sorted array.
For characters in strings,
“greater than” means “appears later in the alphabet than”.
This means that the letter `"B"` is “greater than” the letter `"A"`,
and the string `"Tom"` is greater than the string `"Tim"`.
This gives a reverse alphabetical sort,
with `"Barry"` being placed before `"Alex"`, and so on.
However, this is a rather long-winded way to write
what is essentially a single-expression function (`a > b`).
In this example, it would be preferable to write the sorting closure inline,
using closure expression syntax.
### Closure Expression Syntax
Closure expression syntax has the following general form:
```swift
{ (<#parameters#>) -> <#return type#> in
<#statements#>
}
```
The *parameters* in closure expression syntax
can be in-out parameters,
but they can't have a default value.
Variadic parameters can be used if you name the variadic parameter.
Tuples can also be used as parameter types and return types.
The example below shows a closure expression version of the `backward(_:_:)` function
from above:
```swift
reversedNames = names.sorted(by: { (s1: String, s2: String) -> Bool in
return s1 > s2
})
```
<!--
- test: `closureSyntax`
```swifttest
-> reversedNames = names.sorted(by: { (s1: String, s2: String) -> Bool in
return s1 > s2
})
>> assert(reversedNames == ["Ewa", "Daniella", "Chris", "Barry", "Alex"])
```
-->
Note that the declaration of parameters and return type for this inline closure
is identical to the declaration from the `backward(_:_:)` function.
In both cases, it's written as `(s1: String, s2: String) -> Bool`.
However, for the inline closure expression,
the parameters and return type are written *inside* the curly braces,
not outside of them.
The start of the closure's body is introduced by the `in` keyword.
This keyword indicates that
the definition of the closure's parameters and return type has finished,
and the body of the closure is about to begin.
Because the body of the closure is so short,
it can even be written on a single line:
```swift
reversedNames = names.sorted(by: { (s1: String, s2: String) -> Bool in return s1 > s2 } )
```
<!--
- test: `closureSyntax`
```swifttest
-> reversedNames = names.sorted(by: { (s1: String, s2: String) -> Bool in return s1 > s2 } )
>> assert(reversedNames == ["Ewa", "Daniella", "Chris", "Barry", "Alex"])
```
-->
This illustrates that the overall call to the `sorted(by:)` method has remained the same.
A pair of parentheses still wrap the entire argument for the method.
However, that argument is now an inline closure.
### Inferring Type From Context
Because the sorting closure is passed as an argument to a method,
Swift can infer the types of its parameters
and the type of the value it returns.
The `sorted(by:)` method is being called on an array of strings,
so its argument must be a function of type `(String, String) -> Bool`.
This means that the `(String, String)` and `Bool` types don't need to be written
as part of the closure expression's definition.
Because all of the types can be inferred,
the return arrow (`->`) and the parentheses around the names of the parameters
can also be omitted:
```swift
reversedNames = names.sorted(by: { s1, s2 in return s1 > s2 } )
```
<!--
- test: `closureSyntax`
```swifttest
-> reversedNames = names.sorted(by: { s1, s2 in return s1 > s2 } )
>> assert(reversedNames == ["Ewa", "Daniella", "Chris", "Barry", "Alex"])
```
-->
It's always possible to infer the parameter types and return type
when passing a closure to a function or method as an inline closure expression.
As a result, you never need to write an inline closure in its fullest form
when the closure is used as a function or method argument.
Nonetheless, you can still make the types explicit if you wish,
and doing so is encouraged if it avoids ambiguity for readers of your code.
In the case of the `sorted(by:)` method,
the purpose of the closure is clear from the fact that sorting is taking place,
and it's safe for a reader to assume that
the closure is likely to be working with `String` values,
because it's assisting with the sorting of an array of strings.
### Implicit Returns from Single-Expression Closures
Single-expression closures can implicitly return the result of their single expression
by omitting the `return` keyword from their declaration,
as in this version of the previous example:
```swift
reversedNames = names.sorted(by: { s1, s2 in s1 > s2 } )
```
<!--
- test: `closureSyntax`
```swifttest
-> reversedNames = names.sorted(by: { s1, s2 in s1 > s2 } )
>> assert(reversedNames == ["Ewa", "Daniella", "Chris", "Barry", "Alex"])
```
-->
Here, the function type of the `sorted(by:)` method's argument
makes it clear that a `Bool` value must be returned by the closure.
Because the closure's body contains a single expression (`s1 > s2`)
that returns a `Bool` value,
there's no ambiguity, and the `return` keyword can be omitted.
### Shorthand Argument Names
Swift automatically provides shorthand argument names to inline closures,
which can be used to refer to the values of the closure's arguments
by the names `$0`, `$1`, `$2`, and so on.
If you use these shorthand argument names within your closure expression,
you can omit the closure's argument list from its definition.
The type of the shorthand argument names
is inferred from the expected function type,
and the highest numbered shorthand argument you use
determines the number of arguments that the closure takes.
The `in` keyword can also be omitted,
because the closure expression is made up entirely of its body:
```swift
reversedNames = names.sorted(by: { $0 > $1 } )
```
<!--
- test: `closureSyntax`
```swifttest
-> reversedNames = names.sorted(by: { $0 > $1 } )
>> assert(reversedNames == ["Ewa", "Daniella", "Chris", "Barry", "Alex"])
```
-->
Here, `$0` and `$1` refer to the closure's first and second `String` arguments.
Because `$1` is the shorthand argument with highest number,
the closure is understood to take two arguments.
Because the `sorted(by:)` function here expects a closure
whose arguments are both strings,
the shorthand arguments `$0` and `$1` are both of type `String`.
<!--
- test: `closure-syntax-arity-inference`
```swifttest
>> let a: [String: String] = [:]
>> var b: [String: String] = [:]
>> b.merge(a, uniquingKeysWith: { $1 })
>> b.merge(a, uniquingKeysWith: { $0 })
!$ error: contextual closure type '(String, String) throws -> String' expects 2 arguments, but 1 was used in closure body
!! b.merge(a, uniquingKeysWith: { $0 })
!! ^
```
-->
### Operator Methods
There's actually an even *shorter* way to write the closure expression above.
Swift's `String` type defines its string-specific implementation of
the greater-than operator (`>`)
as a method that has two parameters of type `String`,
and returns a value of type `Bool`.
This exactly matches the method type needed by the `sorted(by:)` method.
Therefore, you can simply pass in the greater-than operator,
and Swift will infer that you want to use its string-specific implementation:
```swift
reversedNames = names.sorted(by: >)
```
<!--
- test: `closureSyntax`
```swifttest
-> reversedNames = names.sorted(by: >)
>> assert(reversedNames == ["Ewa", "Daniella", "Chris", "Barry", "Alex"])
```
-->
For more about operator methods, see <doc:AdvancedOperators#Operator-Methods>.
## Trailing Closures
If you need to pass a closure expression to a function as the function's final argument
and the closure expression is long,
it can be useful to write it as a *trailing closure* instead.
You write a trailing closure after the function call's parentheses,
even though the trailing closure is still an argument to the function.
When you use the trailing closure syntax,
you don't write the argument label for the first closure
as part of the function call.
A function call can include multiple trailing closures;
however, the first few examples below use a single trailing closure.
```swift
func someFunctionThatTakesAClosure(closure: () -> Void) {
// function body goes here
}
// Here's how you call this function without using a trailing closure:
someFunctionThatTakesAClosure(closure: {
// closure's body goes here
})
// Here's how you call this function with a trailing closure instead:
someFunctionThatTakesAClosure() {
// trailing closure's body goes here
}
```
<!--
- test: `closureSyntax`
```swifttest
-> func someFunctionThatTakesAClosure(closure: () -> Void) {
// function body goes here
}
-> // Here's how you call this function without using a trailing closure:
-> someFunctionThatTakesAClosure(closure: {
// closure's body goes here
})
-> // Here's how you call this function with a trailing closure instead:
-> someFunctionThatTakesAClosure() {
// trailing closure's body goes here
}
```
-->
The string-sorting closure from the <doc:Closures#Closure-Expression-Syntax> section above
can be written outside of the `sorted(by:)` method's parentheses as a trailing closure:
```swift
reversedNames = names.sorted() { $0 > $1 }
```
<!--
- test: `closureSyntax`
```swifttest
-> reversedNames = names.sorted() { $0 > $1 }
>> assert(reversedNames == ["Ewa", "Daniella", "Chris", "Barry", "Alex"])
```
-->
If a closure expression is provided as the function's or method's only argument
and you provide that expression as a trailing closure,
you don't need to write a pair of parentheses `()`
after the function or method's name when you call the function:
```swift
reversedNames = names.sorted { $0 > $1 }
```
<!--
- test: `closureSyntax`
```swifttest
-> reversedNames = names.sorted { $0 > $1 }
>> assert(reversedNames == ["Ewa", "Daniella", "Chris", "Barry", "Alex"])
```
-->
Trailing closures are most useful when the closure is sufficiently long that
it isn't possible to write it inline on a single line.
As an example, Swift's `Array` type has a `map(_:)` method,
which takes a closure expression as its single argument.
The closure is called once for each item in the array,
and returns an alternative mapped value (possibly of some other type) for that item.
You specify
the nature of the mapping and the type of the returned value
by writing code in the closure that you pass to `map(_:)`.
After applying the provided closure to each array element,
the `map(_:)` method returns a new array containing all of the new mapped values,
in the same order as their corresponding values in the original array.
Here's how you can use the `map(_:)` method with a trailing closure
to convert an array of `Int` values into an array of `String` values.
The array `[16, 58, 510]` is used to create the new array
`["OneSix", "FiveEight", "FiveOneZero"]`:
```swift
let digitNames = [
0: "Zero", 1: "One", 2: "Two", 3: "Three", 4: "Four",
5: "Five", 6: "Six", 7: "Seven", 8: "Eight", 9: "Nine"
]
let numbers = [16, 58, 510]
```
<!--
- test: `arrayMap`
```swifttest
-> let digitNames = [
0: "Zero", 1: "One", 2: "Two", 3: "Three", 4: "Four",
5: "Five", 6: "Six", 7: "Seven", 8: "Eight", 9: "Nine"
]
-> let numbers = [16, 58, 510]
```
-->
The code above creates a dictionary of mappings between
the integer digits and English-language versions of their names.
It also defines an array of integers, ready to be converted into strings.
You can now use the `numbers` array to create an array of `String` values,
by passing a closure expression to the array's `map(_:)` method as a trailing closure:
```swift
let strings = numbers.map { (number) -> String in
var number = number
var output = ""
repeat {
output = digitNames[number % 10]! + output
number /= 10
} while number > 0
return output
}
// strings is inferred to be of type [String]
// its value is ["OneSix", "FiveEight", "FiveOneZero"]
```
<!--
- test: `arrayMap`
```swifttest
-> let strings = numbers.map { (number) -> String in
var number = number
var output = ""
repeat {
output = digitNames[number % 10]! + output
number /= 10
} while number > 0
return output
}
// strings is inferred to be of type [String]
/> its value is [\"\(strings[0])\", \"\(strings[1])\", \"\(strings[2])\"]
</ its value is ["OneSix", "FiveEight", "FiveOneZero"]
```
-->
The `map(_:)` method calls the closure expression once for each item in the array.
You don't need to specify the type of the closure's input parameter, `number`,
because the type can be inferred from the values in the array to be mapped.
In this example,
the variable `number` is initialized with the value of the closure's `number` parameter,
so that the value can be modified within the closure body.
(The parameters to functions and closures are always constants.)
The closure expression also specifies a return type of `String`,
to indicate the type that will be stored in the mapped output array.
The closure expression builds a string called `output` each time it's called.
It calculates the last digit of `number` by using the remainder operator (`number % 10`),
and uses this digit to look up an appropriate string in the `digitNames` dictionary.
The closure can be used to create a string representation of any integer greater than zero.
> Note: The call to the `digitNames` dictionary's subscript
> is followed by an exclamation point (`!`),
> because dictionary subscripts return an optional value
> to indicate that the dictionary lookup can fail if the key doesn't exist.
> In the example above, it's guaranteed that `number % 10`
> will always be a valid subscript key for the `digitNames` dictionary,
> and so an exclamation point is used to force-unwrap the `String` value
> stored in the subscript's optional return value.
The string retrieved from the `digitNames` dictionary
is added to the *front* of `output`,
effectively building a string version of the number in reverse.
(The expression `number % 10` gives a value of
`6` for `16`, `8` for `58`, and `0` for `510`.)
The `number` variable is then divided by `10`.
Because it's an integer, it's rounded down during the division,
so `16` becomes `1`, `58` becomes `5`, and `510` becomes `51`.
The process is repeated until `number` is equal to `0`,
at which point the `output` string is returned by the closure,
and is added to the output array by the `map(_:)` method.
The use of trailing closure syntax in the example above
neatly encapsulates the closure's functionality
immediately after the function that closure supports,
without needing to wrap the entire closure within
the `map(_:)` method's outer parentheses.
If a function takes multiple closures,
you omit the argument label for the first trailing closure
and you label the remaining trailing closures.
For example,
the function below loads a picture for a photo gallery:
```swift
func loadPicture(from server: Server, completion: (Picture) -> Void, onFailure: () -> Void) {
if let picture = download("photo.jpg", from: server) {
completion(picture)
} else {
onFailure()
}
}
```
<!--
- test: `multiple-trailing-closures`
```swifttest
>> struct Server { }
>> struct Picture { }
>> func download(_ path: String, from server: Server) -> Picture? {
>> return Picture()
>> }
-> func loadPicture(from server: Server, completion: (Picture) -> Void, onFailure: () -> Void) {
if let picture = download("photo.jpg", from: server) {
completion(picture)
} else {
onFailure()
}
}
```
-->
When you call this function to load a picture,
you provide two closures.
The first closure is a completion handler
that displays a picture after a successful download.
The second closure is an error handler
that displays an error to the user.
```swift
loadPicture(from: someServer) { picture in
someView.currentPicture = picture
} onFailure: {
print("Couldn't download the next picture.")
}
```
<!--
- test: `multiple-trailing-closures`
```swifttest
>> struct View {
>> var currentPicture = Picture() { didSet { print("Changed picture") } }
>> }
>> var someView = View()
>> let someServer = Server()
-> loadPicture(from: someServer) { picture in
someView.currentPicture = picture
} onFailure: {
print("Couldn't download the next picture.")
}
<< Changed picture
```
-->
In this example,
the `loadPicture(from:completion:onFailure:)` function
dispatches its network task into the background,
and calls one of the two completion handlers when the network task finishes.
Writing the function this way lets you cleanly separate the code
that's responsible for handling a network failure
from the code that updates the user interface after a successful download,
instead of using just one closure that handles both circumstances.
> Note: Completion handlers can become hard to read,
> especially when you have to nest multiple handlers.
> An alternate approach is to use asynchronous code,
> as described in <doc:Concurrency>.
## Capturing Values
A closure can *capture* constants and variables
from the surrounding context in which it's defined.
The closure can then refer to and modify
the values of those constants and variables from within its body,
even if the original scope that defined the constants and variables no longer exists.
In Swift, the simplest form of a closure that can capture values is a nested function,
written within the body of another function.
A nested function can capture any of its outer function's arguments
and can also capture any constants and variables defined within the outer function.
Here's an example of a function called `makeIncrementer`,
which contains a nested function called `incrementer`.
The nested `incrementer()` function captures two values,
`runningTotal` and `amount`,
from its surrounding context.
After capturing these values,
`incrementer` is returned by `makeIncrementer` as a closure
that increments `runningTotal` by `amount` each time it's called.
```swift
func makeIncrementer(forIncrement amount: Int) -> () -> Int {
var runningTotal = 0
func incrementer() -> Int {
runningTotal += amount
return runningTotal
}
return incrementer
}
```
<!--
- test: `closures`
```swifttest
-> func makeIncrementer(forIncrement amount: Int) -> () -> Int {
var runningTotal = 0
func incrementer() -> Int {
runningTotal += amount
return runningTotal
}
return incrementer
}
```
-->
The return type of `makeIncrementer` is `() -> Int`.
This means that it returns a *function*, rather than a simple value.
The function it returns has no parameters,
and returns an `Int` value each time it's called.
To learn how functions can return other functions,
see <doc:Functions#Function-Types-as-Return-Types>.
The `makeIncrementer(forIncrement:)` function defines an integer variable called `runningTotal`,
to store the current running total of the incrementer that will be returned.
This variable is initialized with a value of `0`.
The `makeIncrementer(forIncrement:)` function has a single `Int` parameter
with an argument label of `forIncrement`, and a parameter name of `amount`.
The argument value passed to this parameter specifies
how much `runningTotal` should be incremented by
each time the returned incrementer function is called.
The `makeIncrementer` function defines a nested function called `incrementer`,
which performs the actual incrementing.
This function simply adds `amount` to `runningTotal`, and returns the result.
When considered in isolation,
the nested `incrementer()` function might seem unusual:
```swift
func incrementer() -> Int {
runningTotal += amount
return runningTotal
}
```
<!--
- test: `closuresPullout`
```swifttest
-> func incrementer() -> Int {
>> var runningTotal = 0
>> let amount = 1
runningTotal += amount
return runningTotal
}
```
-->
The `incrementer()` function doesn't have any parameters,
and yet it refers to `runningTotal` and `amount` from within its function body.
It does this by capturing a *reference* to `runningTotal` and `amount`
from the surrounding function and using them within its own function body.
Capturing by reference ensures that `runningTotal` and `amount` don't disappear
when the call to `makeIncrementer` ends,
and also ensures that `runningTotal` is available
the next time the `incrementer` function is called.
> Note: As an optimization,
> Swift may instead capture and store a *copy* of a value
> if that value isn't mutated by a closure,
> and if the value isn't mutated after the closure is created.
>
> Swift also handles all memory management involved in disposing of
> variables when they're no longer needed.
Here's an example of `makeIncrementer` in action:
```swift
let incrementByTen = makeIncrementer(forIncrement: 10)
```
<!--
- test: `closures`
```swifttest
-> let incrementByTen = makeIncrementer(forIncrement: 10)
```
-->
This example sets a constant called `incrementByTen`
to refer to an incrementer function that adds `10` to
its `runningTotal` variable each time it's called.
Calling the function multiple times shows this behavior in action:
```swift
incrementByTen()
// returns a value of 10
incrementByTen()
// returns a value of 20
incrementByTen()
// returns a value of 30
```
<!--
- test: `closures`
```swifttest
>> let r0 =
-> incrementByTen()
/> returns a value of \(r0)
</ returns a value of 10
>> let r1 =
-> incrementByTen()
/> returns a value of \(r1)
</ returns a value of 20
>> let r2 =
-> incrementByTen()
/> returns a value of \(r2)
</ returns a value of 30
```
-->
<!--
Rewrite the above to avoid discarding the function's return value.
Tracking bug is <rdar://problem/35301593>
-->
If you create a second incrementer,
it will have its own stored reference to a new, separate `runningTotal` variable:
```swift
let incrementBySeven = makeIncrementer(forIncrement: 7)
incrementBySeven()
// returns a value of 7
```
<!--
- test: `closures`
```swifttest
-> let incrementBySeven = makeIncrementer(forIncrement: 7)
>> let r3 =
-> incrementBySeven()
/> returns a value of \(r3)
</ returns a value of 7
```
-->
Calling the original incrementer (`incrementByTen`) again
continues to increment its own `runningTotal` variable,
and doesn't affect the variable captured by `incrementBySeven`:
```swift
incrementByTen()
// returns a value of 40
```
<!--
- test: `closures`
```swifttest
>> let r4 =
-> incrementByTen()
/> returns a value of \(r4)
</ returns a value of 40
```
-->
> Note: If you assign a closure to a property of a class instance,
> and the closure captures that instance by referring to the instance or its members,
> you will create a strong reference cycle between the closure and the instance.
> Swift uses *capture lists* to break these strong reference cycles.
> For more information, see <doc:AutomaticReferenceCounting#Strong-Reference-Cycles-for-Closures>.
## Closures Are Reference Types
In the example above,
`incrementBySeven` and `incrementByTen` are constants,
but the closures these constants refer to are still able to increment
the `runningTotal` variables that they have captured.
This is because functions and closures are *reference types*.
Whenever you assign a function or a closure to a constant or a variable,
you are actually setting that constant or variable to be
a *reference* to the function or closure.
In the example above,
it's the choice of closure that `incrementByTen` *refers to* that's constant,
and not the contents of the closure itself.
This also means that if you assign a closure to two different constants or variables,
both of those constants or variables refer to the same closure.
```swift
let alsoIncrementByTen = incrementByTen
alsoIncrementByTen()
// returns a value of 50
incrementByTen()
// returns a value of 60
```
<!--
- test: `closures`
```swifttest
-> let alsoIncrementByTen = incrementByTen
>> let r5 =
-> alsoIncrementByTen()
/> returns a value of \(r5)
</ returns a value of 50
>> let r6 =
-> incrementByTen()
/> returns a value of \(r6)
</ returns a value of 60
```
-->
The example above shows that calling `alsoIncrementByTen`
is the same as calling `incrementByTen`.
Because both of them refer to the same closure,
they both increment and return the same running total.
## Escaping Closures
A closure is said to *escape* a function
when the closure is passed as an argument to the function,
but is called after the function returns.
When you declare a function that takes a closure as one of its parameters,
you can write `@escaping` before the parameter's type
to indicate that the closure is allowed to escape.
One way that a closure can escape
is by being stored in a variable that's defined outside the function.
As an example,
many functions that start an asynchronous operation
take a closure argument as a completion handler.
The function returns after it starts the operation,
but the closure isn't called until the operation is completed ---
the closure needs to escape, to be called later.
For example:
```swift
var completionHandlers: [() -> Void] = []
func someFunctionWithEscapingClosure(completionHandler: @escaping () -> Void) {
completionHandlers.append(completionHandler)
}
```
<!--
- test: `noescape-closure-as-argument, implicit-self-struct`
```swifttest
-> var completionHandlers: [() -> Void] = []
-> func someFunctionWithEscapingClosure(completionHandler: @escaping () -> Void) {
completionHandlers.append(completionHandler)
}
```
-->
The `someFunctionWithEscapingClosure(_:)` function takes a closure as its argument
and adds it to an array that's declared outside the function.
If you didn't mark the parameter of this function with `@escaping`,
you would get a compile-time error.
An escaping closure that refers to `self`
needs special consideration if `self` refers to an instance of a class.
Capturing `self` in an escaping closure
makes it easy to accidentally create a strong reference cycle.
For information about reference cycles,
see <doc:AutomaticReferenceCounting>.
Normally, a closure captures variables implicitly
by using them in the body of the closure,
but in this case you need to be explicit.
If you want to capture `self`,
write `self` explicitly when you use it,
or include `self` in the closure's capture list.
Writing `self` explicitly lets you express your intent,
and reminds you to confirm that there isn't a reference cycle.
For example, in the code below,
the closure passed to `someFunctionWithEscapingClosure(_:)`
refers to `self` explicitly.
In contrast, the closure passed to `someFunctionWithNonescapingClosure(_:)`
is a nonescaping closure, which means it can refer to `self` implicitly.
```swift
func someFunctionWithNonescapingClosure(closure: () -> Void) {
closure()
}
class SomeClass {
var x = 10
func doSomething() {
someFunctionWithEscapingClosure { self.x = 100 }
someFunctionWithNonescapingClosure { x = 200 }
}
}
let instance = SomeClass()
instance.doSomething()
print(instance.x)
// Prints "200".
completionHandlers.first?()
print(instance.x)
// Prints "100".
```
<!--
- test: `noescape-closure-as-argument`
```swifttest
-> func someFunctionWithNonescapingClosure(closure: () -> Void) {
closure()
}
-> class SomeClass {
var x = 10
func doSomething() {
someFunctionWithEscapingClosure { self.x = 100 }
someFunctionWithNonescapingClosure { x = 200 }
}
}
-> let instance = SomeClass()
-> instance.doSomething()
-> print(instance.x)
<- 200
-> completionHandlers.first?()
-> print(instance.x)
<- 100
```
-->
Here's a version of `doSomething()` that captures `self`
by including it in the closure's capture list,
and then refers to `self` implicitly:
```swift
class SomeOtherClass {
var x = 10
func doSomething() {
someFunctionWithEscapingClosure { [self] in x = 100 }
someFunctionWithNonescapingClosure { x = 200 }
}
}
```
<!--
- test: `noescape-closure-as-argument`
```swifttest
-> class SomeOtherClass {
var x = 10
func doSomething() {
someFunctionWithEscapingClosure { [self] in x = 100 }
someFunctionWithNonescapingClosure { x = 200 }
}
}
>> completionHandlers = []
>> let instance2 = SomeOtherClass()
>> instance2.doSomething()
>> print(instance2.x)
<< 200
>> completionHandlers.first?()
>> print(instance2.x)
<< 100
```
-->
If `self` is an instance of a structure or an enumeration,
you can always refer to `self` implicitly.
However,
an escaping closure can't capture a mutable reference to `self`
when `self` is an instance of a structure or an enumeration.
Structures and enumerations dont allow shared mutability,
as discussed in <doc:ClassesAndStructures#Structures-and-Enumerations-Are-Value-Types>.
```swift
struct SomeStruct {
var x = 10
mutating func doSomething() {
someFunctionWithNonescapingClosure { x = 200 } // OK
someFunctionWithEscapingClosure { x = 100 } // Error
}
}
```
<!--
- test: `struct-capture-mutable-self`
```swifttest
>> var completionHandlers: [() -> Void] = []
>> func someFunctionWithEscapingClosure(completionHandler: @escaping () -> Void) {
>> completionHandlers.append(completionHandler)
>> }
>> func someFunctionWithNonescapingClosure(closure: () -> Void) {
>> closure()
>> }
-> struct SomeStruct {
var x = 10
mutating func doSomething() {
someFunctionWithNonescapingClosure { x = 200 } // OK
someFunctionWithEscapingClosure { x = 100 } // Error
}
}
!$ error: escaping closure captures mutating 'self' parameter
!! someFunctionWithEscapingClosure { x = 100 } // Error
!! ^
!$ note: captured here
!! someFunctionWithEscapingClosure { x = 100 } // Error
!! ^
```
-->
The call to the `someFunctionWithEscapingClosure` function
in the example above is an error
because it's inside a mutating method,
so `self` is mutable.
That violates the rule that escaping closures can't capture
a mutable reference to `self` for structures.
<!--
- test: `noescape-closure-as-argument`
```swifttest
// Test the non-error portion of struct-capture-mutable-self
>> struct SomeStruct {
>> var x = 10
>> mutating func doSomething() {
>> someFunctionWithNonescapingClosure { x = 200 }
>> }
>> }
>> completionHandlers = []
>> var instance3 = SomeStruct()
>> instance3.doSomething()
>> print(instance3.x)
<< 200
```
-->
<!--
- test: `noescape-closure-as-argument`
```swifttest
>> struct S {
>> var x = 10
>> func doSomething() {
>> someFunctionWithEscapingClosure { print(x) } // OK
>> }
>> }
>> completionHandlers = []
>> var s = S()
>> s.doSomething()
>> s.x = 99 // No effect on self.x already captured -- S is a value type
>> completionHandlers.first?()
<< 10
```
-->
## Autoclosures
An *autoclosure* is a closure that's automatically created
to wrap an expression that's being passed as an argument to a function.
It doesn't take any arguments,
and when it's called, it returns the value
of the expression that's wrapped inside of it.
This syntactic convenience lets you omit braces around a function's parameter
by writing a normal expression instead of an explicit closure.
It's common to *call* functions that take autoclosures,
but it's not common to *implement* that kind of function.
For example,
the `assert(condition:message:file:line:)` function
takes an autoclosure for its `condition` and `message` parameters;
its `condition` parameter is evaluated only in debug builds
and its `message` parameter is evaluated only if `condition` is `false`.
An autoclosure lets you delay evaluation,
because the code inside isn't run until you call the closure.
Delaying evaluation is useful for code
that has side effects or is computationally expensive,
because it lets you control when that code is evaluated.
The code below shows how a closure delays evaluation.
```swift
var customersInLine = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
print(customersInLine.count)
// Prints "5".
let customerProvider = { customersInLine.remove(at: 0) }
print(customersInLine.count)
// Prints "5".
print("Now serving \(customerProvider())!")
// Prints "Now serving Chris!"
print(customersInLine.count)
// Prints "4".
```
<!--
- test: `autoclosures`
```swifttest
-> var customersInLine = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
-> print(customersInLine.count)
<- 5
-> let customerProvider = { customersInLine.remove(at: 0) }
-> print(customersInLine.count)
<- 5
-> print("Now serving \(customerProvider())!")
<- Now serving Chris!
-> print(customersInLine.count)
<- 4
```
-->
<!--
Using remove(at:) instead of popFirst() because the latter only works
with ArraySlice, not with Array:
customersInLine[0..<3].popLast() // fine
customersInLine[0..<3].popFirst() // fine
customersInLine.popLast() // fine
customersInLine.popFirst() // FAIL
It also returns an optional, which complicates the listing.
-->
<!--
TODO: It may be worth describing the differences between ``lazy`` and autoclousures.
-->
Even though the first element of the `customersInLine` array is removed
by the code inside the closure,
the array element isn't removed until the closure is actually called.
If the closure is never called,
the expression inside the closure is never evaluated,
which means the array element is never removed.
Note that the type of `customerProvider` isn't `String`
but `() -> String` ---
a function with no parameters that returns a string.
You get the same behavior of delayed evaluation
when you pass a closure as an argument to a function.
```swift
// customersInLine is ["Alex", "Ewa", "Barry", "Daniella"]
func serve(customer customerProvider: () -> String) {
print("Now serving \(customerProvider())!")
}
serve(customer: { customersInLine.remove(at: 0) } )
// Prints "Now serving Alex!"
```
<!--
- test: `autoclosures-function`
```swifttest
>> var customersInLine = ["Alex", "Ewa", "Barry", "Daniella"]
/> customersInLine is \(customersInLine)
</ customersInLine is ["Alex", "Ewa", "Barry", "Daniella"]
-> func serve(customer customerProvider: () -> String) {
print("Now serving \(customerProvider())!")
}
-> serve(customer: { customersInLine.remove(at: 0) } )
<- Now serving Alex!
```
-->
The `serve(customer:)` function in the listing above
takes an explicit closure that returns a customer's name.
The version of `serve(customer:)` below
performs the same operation but, instead of taking an explicit closure,
it takes an autoclosure
by marking its parameter's type with the `@autoclosure` attribute.
Now you can call the function
as if it took a `String` argument instead of a closure.
The argument is automatically converted to a closure,
because the `customerProvider` parameter's type is marked
with the `@autoclosure` attribute.
```swift
// customersInLine is ["Ewa", "Barry", "Daniella"]
func serve(customer customerProvider: @autoclosure () -> String) {
print("Now serving \(customerProvider())!")
}
serve(customer: customersInLine.remove(at: 0))
// Prints "Now serving Ewa!"
```
<!--
- test: `autoclosures-function-with-autoclosure`
```swifttest
>> var customersInLine = ["Ewa", "Barry", "Daniella"]
/> customersInLine is \(customersInLine)
</ customersInLine is ["Ewa", "Barry", "Daniella"]
-> func serve(customer customerProvider: @autoclosure () -> String) {
print("Now serving \(customerProvider())!")
}
-> serve(customer: customersInLine.remove(at: 0))
<- Now serving Ewa!
```
-->
> Note: Overusing autoclosures can make your code hard to understand.
> The context and function name should make it clear
> that evaluation is being deferred.
If you want an autoclosure that's allowed to escape,
use both the `@autoclosure` and `@escaping` attributes.
The `@escaping` attribute is described above in <doc:Closures#Escaping-Closures>.
```swift
// customersInLine is ["Barry", "Daniella"]
var customerProviders: [() -> String] = []
func collectCustomerProviders(_ customerProvider: @autoclosure @escaping () -> String) {
customerProviders.append(customerProvider)
}
collectCustomerProviders(customersInLine.remove(at: 0))
collectCustomerProviders(customersInLine.remove(at: 0))
print("Collected \(customerProviders.count) closures.")
// Prints "Collected 2 closures."
for customerProvider in customerProviders {
print("Now serving \(customerProvider())!")
}
// Prints "Now serving Barry!"
// Prints "Now serving Daniella!"
```
<!--
- test: `autoclosures-function-with-escape`
```swifttest
>> var customersInLine = ["Barry", "Daniella"]
/> customersInLine is \(customersInLine)
</ customersInLine is ["Barry", "Daniella"]
-> var customerProviders: [() -> String] = []
-> func collectCustomerProviders(_ customerProvider: @autoclosure @escaping () -> String) {
customerProviders.append(customerProvider)
}
-> collectCustomerProviders(customersInLine.remove(at: 0))
-> collectCustomerProviders(customersInLine.remove(at: 0))
-> print("Collected \(customerProviders.count) closures.")
<- Collected 2 closures.
-> for customerProvider in customerProviders {
print("Now serving \(customerProvider())!")
}
<- Now serving Barry!
<- Now serving Daniella!
```
-->
In the code above,
instead of calling the closure passed to it
as its `customerProvider` argument,
the `collectCustomerProviders(_:)` function
appends the closure to the `customerProviders` array.
The array is declared outside the scope of the function,
which means the closures in the array can be executed after the function returns.
As a result,
the value of the `customerProvider` argument
must be allowed to escape the function's scope.
<!--
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
-->