Основы Swift / 8.2. Функции - Основы 2


Видео


Ярлыки аргументов функции и имена параметров
Каждый параметр функции имеет и ярлык аргумента, и имя параметра. Ярлык аргумента используется, когда вызывается функция; каждый аргумент записывается в вызове функции с ярлыками аргументов перед ними. Имя параметра используется в реализации функции. По умолчанию, параметры используют их имена в качестве их же ярлыков аргументов.

Все параметры имеют уникальные имена. И хотя возможно для нескольких параметров иметь один ярлык аргумента, уникальные ярлыки аргументов помогают сделать Ваш код более читаемым.
@{8.2\1}
func someFunction(firstParameterName: Int, secondParameterName: Int) {
    // В теле функции firstParameterName и secondParameterName
    // есть названия для первого и второго аргумента функции.
}
someFunction(firstParameterName: 1, secondParameterName: 2)
Указание ярлыков аргументов
Вы можете записать ярлык аргумента перед именем параметра, разделив их пробелом:
@{8.2\2}
func someFunction(argumentLabel parameterName: Int) {
    // В теле функции parameterName ссылается на значение аргумента
    // для этого параметра.
}
Польза от ярлыков аргументов
Использование ярлыков аргументов может позволить функции быть вызываемой в более выразительной форме, похожей на написание предложений, при этом с сохранением тела функции, которое является читаемым и простым к пониманию.
@{8.2\3}
Здесь представлена вариация функции greet(person:), которая принимает имя человека и его родной город и возвращает приветствие.
func greet(person: String, from hometown: String) -> String {
    return "Здравствуй, \(person)!  Рады видеть Вас в \(hometown)."
}
print(greet(person: "Валерия", from: "Барселоне"))
// Печатает "Здравствуй, Валерия!  Рады видеть Вас в Барселоне."
Опускание ярлыков аргументов
Если Вы не хотите использовать ярлык аргумента для параметра, напишите символ нижнего подчёркивания (_) вместо явного ярлыка аргумента для этого параметра.

Если параметр имеет ярлык аргумента, то аргумент должен быть помечен, когда Вы вызываете функцию.
@{8.2\4}
func someFunction(_ firstParameterName: Int, secondParameterName: Int) {
    // В теле функции firstParameterName и secondParameterName
    // есть названия для первого и второго аргумента функции.
}
someFunction(1, secondParameterName: 2)
Значения параметров по-умолчанию
Вы можете определить значение по-умолчанию для любого параметра в функции, присвоим его значение параметру после типа параметра. Если значение по-умолчанию задано, то Вы можете опустить этот параметр при вызове функции.

Разместите параметры без значений по-умолчанию в начале списка параметров функции перед параметрами, которые имеют дефолтные значения. Параметры, которые не имеют значения по-умолчанию обычно более важны для значения функции - написание их первыми делает более простым распознание того, какая из одинаковых функций была вызвана независимо от того, опущены ли какие-то параметры по-умолчанию.
@{8.2\5}
func someFunction(parameterWithoutDefault: Int, parameterWithDefault: Int = 12) {
    // Если Вы опуститие второй аргумент при вызове функции, тогда
    // значение parameterWithDefault равно 12 внутри тела функции.
}
someFunction(parameterWithoutDefault: 3, parameterWithDefault: 6) // parameterWithDefault равен 6
someFunction(parameterWithoutDefault: 4) // parameterWithDefault равен 12
Функции с переменным числом параметров
Параметр с переменным числом значений принимает нуль или более значений указанного типа. Вы можете использовать вариадик-параметры для указания того, что в параметр может быть передано переменное число входных значений при вызове функции. Вы можете написать вариативные параметры, вставив три символа точки (…) по имени типа параметра.

Значения, переданные в вариативный параметр, становятся доступны внутри тела функции в качестве массива подходящего типа. Например, вариативный параметр с именем numbers и типом Double… станет доступным внутри тела функции в качестве константного массива под названием numbers типа [Double].

Функция может иметь только один вариативный параметр.

Пример вычисляет арифметическое ожидание (также известное как среднее) для списка чисел любой длины:
@{8.2\6}
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)
// возвращает 3.0, что является арифметическим ожиданием этих пяти чисел
arithmeticMean(3, 8.25, 18.75)
// возвращает 10.0, что является арифметическим ожиданием этих трёх чисел
in-out параметры
Параметры функции неизменяемы по умолчанию. Попытка изменить значение параметра функции из тела функции приведёт к ошибке времени компиляции. Это означает, что Вы не можете изменить значение параметра по ошибке. Если Вы хотите изменить значение параметра, и Вы хотите сохранить эти изменения после окончания вызова функции, определите этот параметр как in-out.

Вы можете записать in-out параметр, поставив ключевое слово inout прямо перед типом параметра. Параметр in-out имеет значение, передаваемое в функцию, изменяемое функцией и возвращаемое из функции для замены оригинального значения.

Вы можете передать только переменную в качестве аргумента для in-out параметра. Вы не можете передать константу или литеральное значение в качестве аргумента, так как константы и литералы не могут быть изменены. Вы должны разместить амперсанд (&) прямо перед именем переменной, которую хотите передать в качестве аргумента in-out параметра для того, чтобы указать, что она может быть изменена функцией.

in-out параметры не могут иметь значений по-умолчанию, а вариативные параметры не могут быть промаркированы как inout.

Здесь приведён пример функции под названием swapTwoInts(_:_:), которая имеет два целочисленных параметра с названиями a и b:
@{8.2\7}
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(_:_:):
@{8.2\8}
var someInt = 3
var anotherInt = 107
swapTwoInts(&someInt, &anotherInt)
print("someInt теперь равно \(someInt), и anotherInt теперь равно \(anotherInt)")
Пример демонстрирует, что оригинальные значения someInt и anotherInt изменяются функцией swapTwoInts(_:_:), даже если они были изначально заданы вне функции.

in-out параметры - это не то же самое, что возвращаемое значение функции. Пример выше с swapTwoInts не использует определение возвращаемого типа или не возвращает значения из функции, но всё ещё изменяет значения someInt и anotherInt. Параметры in-out - это альтернативный способ для функции иметь эффект за пределами пространства своего тела.
Именование функций
Когда Вы хотите привести в каком-то тексте название функции, Вам необязательно описывать всё её определение, достаточно лишь указать её названия и ярлыки аргументов в круглых скобках, разделив их двоеточиями: swapTwoInts(_:_:) или greet(person:). Причём двоеточие пишется и после единственного названия аргумента. У вариадик-аргументов ставится троеточие после имени: arithmeticMean(numbers…).
Перегрузка функций
Одна и та же функция (по имени) может иметь несколько вариаций в зависимости от типа принимаемых значений, даже если они имеют одни и те же названия аргументов. Такой подход называется перегрузкой функций:
@{8.2\9}
import Foundation

func absoluteValue(_ x: Double) -> Double {
    return abs(x)
}
func absoluteValue(_ x: Float) -> Float {
    return abs(x)
}
func absoluteValue(_ x: Int) -> Int {
    return abs(x)
}
func absoluteValue(of x: Int) -> Int {
    return abs(x)
}
print(absoluteValue(-10.1))
print(absoluteValue(Float(-10.1)))
print(absoluteValue(-10))
print(absoluteValue(of: -10))
Все три функции имеют название absoluteValue(_:), однако работают они над разными типами и возвращают разные типы. Четвертая функция имеет название absoluteValue(of:) и потому его использование так же допустимо.