func makeInrementer(forIncrement amount: Int) -> () -> Int {
var runningTotal = 0
func incrementer() -> Int {
runningTotal += amount
return runningTotal
}
return incrementer
}
Здесь приведён пример функции с названием makeIncrementer
, которая содержит вложенную функцию с названием incrementer
. Вложенная функция incrementer()
захватывает два значения, runningTotal
и amount
, из своего окружающего контекста. После захвата этих значений incrementer
возвращается makeIncrementer
в качестве замыкания, которое увеличивает runningTotal
на значение amount
всякий раз при своём вызове.
makeInсrementer () -> Int
. Это означает, что он возвращает функцию, а не простое значение. Функция, им возвращаемая, не имеет параметров, а возвращаемое значение всегда имеет при вызове тип Int
.
makeInсrementer(forIncrement:)
определяет целое число-переменную с названием runningTotal
для хранения текущего значения инкрементера. Инициализируется она значением 0.
makeInсrementer(forIncrement:)
имеет единственный параметр типа Int
с ярлыком аргумента forIncrement
и именем параметра amount
. Значение аргумента передаётся в этот параметр для определения того, на сколько должно возрасти значение runningTotal
всякий раз при вызове возвращаемой функции-инкрементера. Функция makeInсrementer
определяет вложенную функцию с названием incrementer
, которая уже осуществляет увеличение. Функция просто прибавляет amount к runningTotal
и возвращает результат.
func incrementer() -> Int {
runningTotal += amount
return runningTotal
}
При отдельном рассмотрении вложенная функция incrementer()
может выглядеть необычной.
incrementer()
не имеет никаких параметров, но всё ещё ссылается на runningTotal
и amount
из своего тела. Это осуществляется с помощью захвата ссылки на runningTotal
и amount
из окружающей функции и использования их внутри своего собственного тела функции. Захват по ссылке определяет, что runningTotal
и amount
не исчезнут после того, как закончится вызов makeInсrementer
, а также то, что runningTotal
будет доступен и при следующем вызове функции.
let incremenetByTen = makeInrementer(forIncrement: 10)
Этот пример устанавливает значение константы под названием incrementByTen
для ссылки на функцию-инкрементер, которая прибавляет 10 к своей переменной runningTotal
всякий раз при вызове функции.
incremenetByTen()
// возвращает значение 10
incremenetByTen()
// возвращает значение 20
incremenetByTen()
// возвращает значение 30
Вызов функции несколько раз покажет её поведение в действии.
runningTotal
.
let incrementBySeven = makeInrementer(forIncrement: 7)
incrementBySeven()
// возвращает значение 7
(incrementByTen)
вновь продолжит увеличивать свою собственную переменную runningTotal
и не окажет эффекта на переменную, захваченную incrementBySeven
.
incremenetByTen()
// возвращает значение 40
incrementBySeven
и incrementByTen
являются константами, но замыкания, на которые ссылаются эти константы, всё ещё могут инкрементировать свои переменные runningTotal
, которые они захватили. Так происходит ввиду того, функции и замыкания - это ссылочные типы.
incrementByTen
, а не то что контент самого замыкания постоянен.
let alsoIncrementByTen = incremenetByTen
alsoIncrementByTen()
// возвращает значение 50