Функции
Определяйте и вызывайте функции, маркируйте их аргументы и используйте возвращаемые значения.
Функции — это самостоятельные блоки кода, выполняющие определённую задачу. Вы даёте функции имя, которое описывает её действие, и это имя используется для «вызова» функции, чтобы она выполнила свою задачу по мере необходимости.
Унифицированный синтаксис функций Swift достаточно гибкий, чтобы выразить всё, начиная от простой функции в стиле C без имён параметров, и заканчивая сложным методом в стиле Objective-C с именами и метками аргументов для каждого параметра. Параметры могут предоставлять значения по умолчанию для упрощения вызовов функций и могут передаваться как параметры in-out, которые изменяют переданную переменную после завершения выполнения функции.
Каждая функция в Swift имеет тип, состоящий из типов параметров функции и типа возвращаемого значения. Вы можете использовать этот тип как любой другой тип в Swift, что делает лёгкой передачу функций в качестве параметров другим функциям и возвращение функций из функций. Функции также могут быть записаны внутри других функций, чтобы инкапсулировать полезную функциональность в области видимости вложенной функции.
Определение и вызов функций
При определении функции вы можете необязательно определить один или несколько именованных значений с типами, которые функция принимает в качестве входных данных, известных как параметры. Вы также можете необязательно определить тип значения, которое функция вернёт в качестве выходных данных, когда она закончит работу, известный как её тип возвращаемого значения.
У каждой функции есть имя функции, которое описывает задачу, выполняемую функцией. Чтобы использовать функцию, вы «вызываете» эту функцию по её имени и передаёте ей входные значения (известные как аргументы), которые соответствуют типам параметров функции. Аргументы функции всегда должны передаваться в том же порядке, что и в списке параметров функции.
Функция в примере ниже называется greet(person:), потому что именно это она делает — она принимает имя человека в качестве входных данных и возвращает приветствие для этого человека. Для этого вы определяете один входной параметр — значение типа String, называемое person, и тип возвращаемого значения String, который будет содержать приветствие для этого человека:
func greet(person: String) -> String {
let greeting = "Hello, " + person + "!"
return greeting
} Вся эта информация сворачивается в определение функции, которая начинается с ключевого слова func. Тип возвращаемого значения функции указывается с помощью стрелки возврата -> (тире, за которым следует знак больше), за которым следует имя возвращаемого типа.
Определение описывает, что делает функция, что она ожидает получить и что возвращает по завершении. Определение упрощает однозначный вызов функции из других частей кода:
print(greet(person: "Anna")) // Prints "Hello, Anna!" print(greet(person: "Brian")) // Prints "Hello, Brian!"
Вызываете функцию greet(person:), передавая ей значение типа String после метки аргумента person, например, greet(person: "Anna"). Поскольку функция возвращает значение типа String, greet(person:) можно заключить в вызов функции print(_:separator:terminator:) для печати этой строки и просмотра её возвращаемого значения, как показано выше.
Примечание: Функция
print(_:separator:terminator:)не имеет метки для своего первого аргумента, а её другие аргументы необязательны, так как у них есть значение по умолчанию. Эти варианты синтаксиса функций обсуждаются ниже в <doc:Functions#Function-Argument-Labels-and-Parameter-Names> и <doc:Functions#Default-Parameter-Values>.
Тело функции greet(person:) начинается с определения новой константы String, называемой greeting, и присвоения ей простого приветствия. Затем это приветствие передаётся обратно из функции с помощью ключевого слова return. В строке кода, которая говорит return greeting, функция завершает своё выполнение и возвращает текущее значение greeting.
Вы можете вызывать функцию greet(person:) несколько раз с разными входными значениями. Пример выше показывает, что произойдёт, если она вызывается со значением входных данных "Anna" и входным значением "Brian". В каждом случае функция возвращает соответствующее приветствие.
Чтобы сделать тело этой функции короче, вы можете объединить создание сообщения и оператор возврата в одну строку:
func greetAgain(person: String) -> String {
return "Hello again, " + person + "!"
}
print(greetAgain(person: "Anna"))
// Prints "Hello again, Anna!" Параметры и возвращаемые значения функции
Параметры и возвращаемые значения функций в Swift очень гибкие. Вы можете определить всё, от простой утилитарной функции с одним безымянным параметром до сложной функции с выразительными именами параметров и различными параметрами.
Функции без параметров
Функции не обязаны определять входные параметры. Вот функция без входных параметров, которая всегда возвращает то же самое String сообщение всякий раз, когда она вызывается:
func sayHelloWorld() -> String {
return "hello, world"
}
print(sayHelloWorld())
// Prints "hello, world" Функция по-прежнему должна иметь круглые скобки после имени функции, даже если она не принимает никаких параметров. Имя функции также следует за пустой парой скобок, когда функция вызывается.
Функции с несколькими параметрами
Функции могут иметь несколько входных параметров, которые записываются в скобки функции, разделённые запятыми.
Эта функция принимает имя человека и информацию о том, уже ли он был приветствован, в качестве входных данных и возвращает соответствующее приветствие для этого человека:
func greet(person: String, alreadyGreeted: Bool) -> String {
if alreadyGreeted {
return greetAgain(person: person)
} else {
return greet(person: person)
}
}
print(greet(person: "Tim", alreadyGreeted: true))
// Prints "Hello again, Tim!" Вызываете функцию greet(person:alreadyGreeted:), передавая ей как значение аргумента String с меткой person, так и значение аргумента Bool с меткой alreadyGreeted в скобках, разделённые запятыми. Обратите внимание, что эта функция отличается от функции greet(person:), показанной в предыдущем разделе. Хотя у обеих функций имена начинаются с greet, функция greet(person:alreadyGreeted:) принимает два аргумента, а функция greet(person:) — только один.
Функции без возвращаемых значений
Функции не обязаны определять тип возвращаемого значения. Вот версия функции greet(person:), которая выводит своё значение String вместо того, чтобы возвращать его:
func greet(person: String) {
print("Hello, \(person)!")
}
greet(person: "Dave")
// Prints "Hello, Dave!" Поскольку ей не нужно возвращать значение, её определение не включает стрелку возврата (->) или тип возвращаемого значения.
Примечание: Строго говоря, эта версия функции
greet(person:)действительно возвращает значение, хотя и не определено никакое возвращаемое значение. Функции без определённого типа возвращаемого значения возвращают специальное значение типаVoid. Это просто пустая кортеж, которая записывается как().
Возвращаемое значение функции можно игнорировать при её вызове:
func printAndCount(string: String) -> Int {
print(string)
return string.count
}
func printWithoutCounting(string: String) {
let _ = printAndCount(string: string)
}
printAndCount(string: "hello, world")
// prints "hello, world" and returns a value of 12
printWithoutCounting(string: "hello, world")
// prints "hello, world" but doesn't return a value Первая функция, printAndCount(string:), выводит строку и затем возвращает её длину в символах как значение типа Int. Вторая функция, printWithoutCounting(string:), вызывает первую функцию, но игнорирует её возвращаемое значение. При вызове второй функции сообщение по-прежнему выводится первой функцией, но возвращаемое значение не используется.
Примечание: Возвращаемые значения можно игнорировать, но функция, которая заявляет о возвращении значения, всегда должна это делать. Функция с определённым типом возвращаемого значения не может позволить выполнению выйти из функции внизу без возврата значения, и попытка сделать это приведёт к ошибке компиляции.
Функции с несколькими возвращаемыми значениями
Вы можете использовать кортеж типов в качестве типа возвращаемого значения функции, чтобы вернуть несколько значений в рамках одного составного возвращаемого значения.
В примере ниже определена функция под названием minMax(array:), которая находит наименьшее и наибольшее числа в массиве значений типа Int:
func minMax(array: [Int]) -> (min: Int, max: Int) {
var currentMin = array[0]
var currentMax = array[0]
for value in array[1..<array.count] {
if value < currentMin {
currentMin = value
} else if value > currentMax {
currentMax = value
}
}
return (currentMin, currentMax)
} Функция minMax(array:) возвращает кортеж, содержащий два значения типа Int. Эти значения помечены как min и max, чтобы к ним можно было получить доступ по имени при запросе возвращаемого значения функции.
Тело функции minMax(array:) начинается с присвоения двух рабочих переменных, currentMin и currentMax, значения первого целого числа в массиве. Затем функция итерирует по остальным значениям в массиве и проверяет каждое значение, чтобы увидеть, меньше или больше ли оно значений currentMin и currentMax соответственно. Наконец, минимальное и максимальное значения возвращаются как кортеж из двух значений типа Int.
Поскольку члены кортежа имеют имена в типе возвращаемого значения функции, к ним можно получить доступ с помощью точечной нотации, чтобы получить минимальное и максимальное найденные значения:
let bounds = minMax(array: [8, -6, 2, 109, 3, 71])
print("min is \(bounds.min) and max is \(bounds.max)")
// Prints "min is -6 and max is 109" Обратите внимание, что члены кортежа не должны иметь имена в момент возвращения кортежа из функции, так как их имена уже указаны в типе возвращаемого значения функции.
Необязательные кортежи типов возвращаемых значений
Если тип кортежа, который должен возвращаться функцией, может иметь «нет значения» для всего кортежа, вы можете использовать необязательный кортеж типов возвращаемых значений, чтобы отразить тот факт, что весь кортеж может быть nil. Вы записываете необязательный кортеж типов возвращаемых значений, поместив вопросительный знак после закрывающей скобки кортежа, например, (Int, Int)? или (String, Int, Bool)?.
Примечание: Необязательный кортеж типа, например,
(Int, Int)?, отличается от кортежа, содержащего необязательные типы, например,(Int?, Int?). В случае необязательного кортежа типа сам кортеж необязателен, а не каждое отдельное значение внутри кортежа.
Функция minMax(array:) выше возвращает кортеж, содержащий два значения типа Int. Однако функция не выполняет никаких проверок безопасности на передаваемый ей массив. Если аргумент array содержит пустой массив, функция minMax(array:), как определена выше, вызовет ошибку выполнения при попытке доступа к array[0].
Чтобы безопасно обработать пустой массив, запишите функцию minMax(array:) с необязательным кортежем типов возвращаемых значений и верните значение nil, когда массив пуст:
func minMax(array: [Int]) -> (min: Int, max: Int)? {
if array.isEmpty { return nil }
var currentMin = array[0]
var currentMax = array[0]
for value in array[1..<array.count] {
if value < currentMin {
currentMin = value
} else if value > currentMax {
currentMax = value
}
}
return (currentMin, currentMax)
} Вы можете использовать привязку к необязательному значению, чтобы проверить, возвращает ли эта версия функции minMax(array:) фактическое значение кортежа или nil:
if let bounds = minMax(array: [8, -6, 2, 109, 3, 71]) {
print("min is \(bounds.min) and max is \(bounds.max)")
}
// Prints "min is -6 and max is 109" Функции с неявным возвратом
Если всё тело функции — это единственное выражение, функция неявно возвращает это выражение. Например, обе функции ниже имеют одинаковое поведение:
func greeting(for person: String) -> String {
"Hello, " + person + "!"
}
print(greeting(for: "Dave"))
// Prints "Hello, Dave!"
func anotherGreeting(for person: String) -> String {
return "Hello, " + person + "!"
}
print(anotherGreeting(for: "Dave"))
// Prints "Hello, Dave!" Всё определение функции greeting(for:) — это возвращаемое сообщение приветствия, что означает, что оно может использовать эту более короткую форму. Функция anotherGreeting(for:) возвращает то же самое сообщение приветствия, используя ключевое слово return, как и более длинная функция. Любая функция, которая записывается как всего одна строка return, может опустить ключевое слово return.
Как вы увидите в <doc:Properties#Shorthand-Getter-Declaration>, геттеры свойств также могут использовать неявное возвращение.
Примечание: код, который вы пишете как значение неявного возвращения, должен возвращать какое-то значение. Например, вы не можете использовать
print(13)в качестве значения неявного возвращения. Однако вы можете использовать функцию, которая никогда не возвращает, например,fatalError("Oh no!"), в качестве значения неявного возвращения, потому что Swift знает, что неявное возвращение не происходит.
Метки аргументов и имена параметров функций
Каждый параметр функции имеет и метку аргумента, и имя параметра. Метка аргумента используется при вызове функции; каждый аргумент записывается в вызове функции со своей меткой аргумента перед ним. Имя параметра используется в реализации функции. По умолчанию параметры используют своё имя параметра в качестве метки аргумента.
func someFunction(firstParameterName: Int, secondParameterName: Int) {
// In the function body, firstParameterName and secondParameterName
// refer to the argument values for the first and second parameters.
}
someFunction(firstParameterName: 1, secondParameterName: 2) Все параметры должны иметь уникальные имена. Хотя несколько параметров могут иметь одинаковую метку аргумента, уникальные метки аргументов помогают сделать ваш код более читаемым.
Определение меток аргументов
Вы пишете метку аргумента перед именем параметра, разделяя их пробелом:
func someFunction(argumentLabel parameterName: Int) {
// In the function body, parameterName refers to the argument value
// for that parameter.
} Вот вариация функции greet(person:), которая принимает имя и родной город человека и возвращает приветствие:
func greet(person: String, from hometown: String) -> String {
return "Hello \(person)! Glad you could visit from \(hometown)."
}
print(greet(person: "Bill", from: "Cupertino"))
// Prints "Hello Bill! Glad you could visit from Cupertino." Использование меток аргументов может позволить функции вызываться выразительным, похожим на предложение способом, сохраняя при этом тело функции удобочитаемым и понятным по своему назначению.
Опускание меток аргументов
Если вы не хотите метку аргумента для параметра, запишите подчёркивание (_) вместо явной метки аргумента для этого параметра.
func someFunction(_ firstParameterName: Int, secondParameterName: Int) {
// In the function body, firstParameterName and secondParameterName
// refer to the argument values for the first and second parameters.
}
someFunction(1, secondParameterName: 2) Если у параметра есть метка аргумента, аргумент обязательно должен быть помечен при вызове функции.
Значения параметров по умолчанию
Вы можете определить значение по умолчанию для любого параметра функции, присвоив ему значение после типа этого параметра. Если определено значение по умолчанию, вы можете опустить этот параметр при вызове функции.
func someFunction(parameterWithoutDefault: Int, parameterWithDefault: Int = 12) {
// If you omit the second argument when calling this function, then
// the value of parameterWithDefault is 12 inside the function body.
}
someFunction(parameterWithoutDefault: 3, parameterWithDefault: 6) // parameterWithDefault is 6
someFunction(parameterWithoutDefault: 4) // parameterWithDefault is 12 Параметры, не имеющие значений по умолчанию, помещайте в начале списка параметров функции перед параметрами, имеющими значения по умолчанию. Параметры без значений по умолчанию, как правило, более важны для смысла функции — их написание вначале упрощает распознание того, что вызывается та же самая функция, независимо от того, опущены ли какие-либо параметры по умолчанию.
Параметры-аргументы
Параметр-аргумент принимает ноль или более значений указанного типа. Вы используете параметр-аргумент для указания того, что параметру может быть передано переменное количество входных значений при вызове функции. Запишите параметры-аргументы, вставив три символа точки (...) после имени типа параметра.
Значения, переданные параметру-аргументу, доступны внутри тела функции как массив соответствующего типа. Например, параметр-аргумент с именем numbers и типом Double... доступен внутри тела функции как константный массив, называемый numbers типа [Double].
В примере ниже вычисляется среднее арифметическое (также известное как среднее значение) для списка чисел любой длины:
func arithmeticMean(_ numbers: Double...) -> Double {
var total: Double = 0
for number in numbers {
total += number
}
return total / Double(numbers.count)
}
arithmeticMean(1, 2, 3, 4, 5)
// returns 3.0, which is the arithmetic mean of these five numbers
arithmeticMean(3, 8.25, 18.75)
// returns 10.0, which is the arithmetic mean of these three numbers Функция может иметь несколько параметров-аргументов. Первый параметр, следующий за параметром-аргументом, должен иметь метку аргумента. Метка аргумента делает недвусмысленным, какие аргументы передаются параметру-аргументу, а какие — параметрам, следующим за параметром-аргументом.
Параметры in-out
Параметры функций по умолчанию являются константами. Попытка изменить значение параметра функции внутри тела этой функции приводит к ошибке на этапе компиляции. Это означает, что вы не можете случайно изменить значение параметра. Если вы хотите, чтобы функция изменяла значение параметра, и вы хотите, чтобы эти изменения сохранялись после завершения вызова функции, определите этот параметр как параметр in-out вместо этого.
Вы пишете параметр in-out, поместив ключевое слово inout непосредственно перед типом параметра. Параметр in-out имеет значение, которое передаётся в функцию, изменяется функцией и передаётся обратно из функции для замены исходного значения. Подробное обсуждение поведения параметров in-out и связанных с ними оптимизаций компилятора см. в <doc:Declarations#In-Out-Parameters>.
Вы можете передать только переменную в качестве аргумента для параметра in-out. Вы не можете передать константу или литеральное значение в качестве аргумента, поскольку константы и литералы не могут быть изменены. Вы помещаете амперсанд (&) непосредственно перед именем переменной, когда передаёте её в качестве аргумента параметру in-out, чтобы указать, что она может быть изменена функцией.
Примечание: параметры in-out не могут иметь значения по умолчанию, и параметры-аргументы не могут быть помечены как
inout.
Вот пример функции, называемой swapTwoInts(_:_:), которая имеет два параметра in-out целого типа, называемые a и b:
func swapTwoInts(_ a: inout Int, _ b: inout Int) {
let temporaryA = a
a = b
b = temporaryA
} Функция swapTwoInts(_:_:) просто меняет местами значение b в a и значение a в b. Функция выполняет эту перестановку, сохраняя значение a в временной константе, называемой temporaryA, присваивая значение b переменной a и затем присваивая temporaryA переменной b.
Вы можете вызвать функцию swapTwoInts(_:_:) с двумя переменными типа Int, чтобы поменять их местами. Обратите внимание, что имена someInt и anotherInt имеют префикс амперсанда, когда они передаются в функцию swapTwoInts(_:_:):
var someInt = 3
var anotherInt = 107
swapTwoInts(&someInt, &anotherInt)
print("someInt is now \(someInt), and anotherInt is now \(anotherInt)")
// Prints "someInt is now 107, and anotherInt is now 3" Приведённый выше пример показывает, что исходные значения someInt и anotherInt изменяются функцией swapTwoInts(_:_:), даже если они были первоначально определены вне функции.
Примечание: параметры in-out не эквивалентны возвращаемому значению функции. Пример с
swapTwoIntsвыше не определяет тип возвращаемого значения или не возвращает значение, но всё равно изменяет значенияsomeIntиanotherInt. Параметры in-out — это альтернативный способ для функции иметь влияние за пределами области её тела функции.
Типы функций
У каждой функции есть определённый тип функции, состоящий из типов параметров и типа возвращаемого значения функции.
Например:
func addTwoInts(_ a: Int, _ b: Int) -> Int {
return a + b
}
func multiplyTwoInts(_ a: Int, _ b: Int) -> Int {
return a * b
} В этом примере определены две простые математические функции, называемые addTwoInts и multiplyTwoInts. Эти функции каждый принимают два значения Int и возвращают значение Int, которое является результатом выполнения соответствующей математической операции.
Тип обеих этих функций — (Int, Int) -> Int. Это можно прочитать как:
«Функция, имеющая два параметра, оба типа Int, и которая возвращает значение типа Int.»
Вот ещё один пример для функции без параметров или возвращаемого значения:
func printHelloWorld() {
print("hello, world")
} Тип этой функции — () -> Void или «функция без параметров, возвращающая Void.»
Использование типов функций
Вы используете типы функций, как и любые другие типы в Swift. Например, вы можете определить константу или переменную типа функции и присвоить ей соответствующую функцию:
var mathFunction: (Int, Int) -> Int = addTwoInts
Это можно прочитать как:
«Определить переменную под названием mathFunction, имеющую тип "функция, которая принимает два значения Int и возвращает значение типа Int". Присвоить этой новой переменной ссылку на функцию под названием addTwoInts.»
Функция addTwoInts(_:_:) имеет тот же тип, что и переменная mathFunction, и поэтому это присвоение разрешено проверкой типов Swift.
Теперь вы можете вызвать присвоенную функцию с именем mathFunction:
print("Result: \(mathFunction(2, 3))")
// Prints "Result: 5" В переменную с таким же сопоставляемым типом может быть присвоена другая функция, так же, как и для типов, не являющихся функциями:
mathFunction = multiplyTwoInts
print("Result: \(mathFunction(2, 3))")
// Prints "Result: 6" Как и с любым другим типом, вы можете позволить Swift вывести тип функции, когда вы присваиваете функцию константе или переменной:
let anotherMathFunction = addTwoInts // anotherMathFunction is inferred to be of type (Int, Int) -> Int
Типы функций как типы параметров
Вы можете использовать тип функции, такой как (Int, Int) -> Int, как тип параметра для другой функции. Это позволяет оставить некоторые аспекты реализации функции для того, чтобы вызывающий функцию предоставил их, когда функция будет вызвана.
Вот пример для вывода результатов математических функций из приведённых выше:
func printMathResult(_ mathFunction: (Int, Int) -> Int, _ a: Int, _ b: Int) {
print("Result: \(mathFunction(a, b))")
}
printMathResult(addTwoInts, 3, 5)
// Prints "Result: 8" В этом примере определена функция под названием printMathResult(_:_:_:), которая имеет три параметра. Первый параметр называется mathFunction и имеет тип (Int, Int) -> Int. Вы можете передать любую функцию этого типа в качестве аргумента для этого первого параметра. Второй и третий параметры называются a и b и оба имеют тип Int. Они используются в качестве двух входных значений для предоставленной математической функции.
Когда printMathResult(_:_:_:) вызывается, ей передаётся функция addTwoInts(_:_:) и целочисленные значения 3 и 5. Она вызывает предоставленную функцию со значениями 3 и 5 и выводит результат 8.
Роль printMathResult(_:_:_:) заключается в выводе результата вызова математической функции соответствующего типа. Неважно, что эта функция фактически делает — важно только то, что она имеет правильный тип. Это позволяет printMathResult(_:_:_:) безопасно с точки зрения типов передать часть своей функциональности вызывающей функции.
Типы функций как типы возвращаемых значений
Вы можете использовать тип функции в качестве типа возвращаемого значения другой функции. Делается это путём написания полного типа функции непосредственно после стрелки возврата (->) возвращаемой функции.
В следующем примере определены две простые функции, называемые stepForward(_:) и stepBackward(_:). Функция stepForward(_:) возвращает значение на единицу больше, чем входное значение, а функция stepBackward(_:) возвращает значение на единицу меньше, чем входное значение. Обе функции имеют тип (Int) -> Int:
func stepForward(_ input: Int) -> Int {
return input + 1
}
func stepBackward(_ input: Int) -> Int {
return input - 1
} Вот функция под названием chooseStepFunction(backward:), тип возвращаемого значения которой — (Int) -> Int. Функция chooseStepFunction(backward:) возвращает функцию stepForward(_:) или функцию stepBackward(_:) в зависимости от булевого параметра под названием backward:
func chooseStepFunction(backward: Bool) -> (Int) -> Int {
return backward ? stepBackward : stepForward
} Теперь вы можете использовать chooseStepFunction(backward:), чтобы получить функцию, которая будет шагать в ту или иную сторону:
var currentValue = 3 let moveNearerToZero = chooseStepFunction(backward: currentValue > 0) // moveNearerToZero now refers to the stepBackward() function
В приведенном выше примере определяется, нужен ли положительный или отрицательный шаг для того, чтобы переменная, называемая currentValue, постепенно приближалась к нулю. currentValue имеет начальное значение 3, что означает, что currentValue > 0 возвращает true, заставляя chooseStepFunction(backward:) вернуть функцию stepBackward(_:). Ссылка на возвращенную функцию хранится в константе под названием moveNearerToZero.
Теперь, когда moveNearerToZero ссылается на правильную функцию, её можно использовать для подсчета до нуля:
print("Counting to zero:")
// Counting to zero:
while currentValue != 0 {
print("\(currentValue)... ")
currentValue = moveNearerToZero(currentValue)
}
print("zero!")
// 3...
// 2...
// 1...
// zero! Вложенные функции
Все функции, с которыми вы сталкивались до сих пор в этой главе, были примерами глобальных функций, определённых на глобальном уровне. Вы также можете определять функции внутри тел других функций, которые называются вложенными функциями.
Вложенные функции по умолчанию скрыты от внешнего мира, но их всё же можно вызывать и использовать внутри содержащей их функции. Содержащая функция также может возвращать одну из своих вложенных функций, чтобы позволить вложенной функции использоваться в другом пространстве имён.
Вы можете переписать пример chooseStepFunction(backward:) выше, используя и возвращая вложенные функции:
func chooseStepFunction(backward: Bool) -> (Int) -> Int {
func stepForward(input: Int) -> Int { return input + 1 }
func stepBackward(input: Int) -> Int { return input - 1 }
return backward ? stepBackward : stepForward
}
var currentValue = -4
let moveNearerToZero = chooseStepFunction(backward: currentValue > 0)
// moveNearerToZero now refers to the nested stepForward() function
while currentValue != 0 {
print("\(currentValue)... ")
currentValue = moveNearerToZero(currentValue)
}
print("zero!")
// -4...
// -3...
// -2...
// -1...
// zero!
This source file is part of the Swift.org open source project
Copyright © 2014 - 2025 Apple Inc. and the Swift project authors
Licensed under Apache License v2.0 with Runtime Library Exception