Функции и параметры

Функция — это именованный блок кода, который выполняет задачу. Хорошие функции делают код читаемым, как хорошо написанный текст.
Суть урока: метки аргументов в Swift делают вызов функции похожим на фразу естественного языка. Это не косметика, а часть культуры читаемого кода.

Функция объявляется ключевым словом func. У параметров есть тип, а после стрелки -> указывается тип возвращаемого значения:

func square(_ number: Int) -> Int {
    return number * number
}
let result = square(5)   // 25

Особенность Swift — метки аргументов. По умолчанию имя параметра становится меткой при вызове, и это читается как предложение:

func greet(person name: String, from city: String) -> String {
    "Привет, \(name) из города \(city)"
}
let msg = greet(person: "Анна", from: "Москвы")
// внешняя метка (person, from) и внутреннее имя (name, city)

Подчёркивание _ убирает метку — тогда аргумент передаётся без подписи. Параметрам можно задать значения по умолчанию:

func makeTea(sugar: Int = 1, milk: Bool = false) -> String {
    "Чай: сахар \(sugar), молоко \(milk)"
}
makeTea()                    // всё по умолчанию
makeTea(sugar: 2)            // только сахар
makeTea(sugar: 0, milk: true)

Обычно параметры неизменяемы внутри функции. Если нужно изменить переданную переменную, используют inout, передавая аргумент со знаком &:

func double(_ value: inout Int) {
    value *= 2
}
var x = 10
double(&x)
print(x)   // 20

Попробуй сам ▶ — запусти код прямо в браузере (Pyodide). Здесь нет Swift, но логика та же, что под капотом мобильного кода:

# Аналог меток аргументов в Python — именованные аргументы и значения по умолчанию.
def make_tea(sugar=1, milk=False):
    return f'Чай: сахар {sugar}, молоко {milk}'

print(make_tea())
print(make_tea(sugar=2))
print(make_tea(sugar=0, milk=True))

def square(number):
    return number * number
print('square(5) =', square(5))

Как работает под капотом

Метки аргументов — часть сигнатуры функции, поэтому greet(person:from:) и greet(name:city:) для компилятора — две разные функции. Параметры по умолчанию передаются по значению (копия), и менять их внутри нельзя. inout работает иначе: значение копируется внутрь, изменяется, и при выходе копируется обратно — отсюда требование передавать переменную через & и невозможность передать константу.

Частые ошибки

  • Забыть метку при вызове. Если параметр не помечен _, метка обязательна.
  • Пытаться изменить обычный параметр. Параметры — константы; для изменения нужен inout.
  • Передать константу в inout. inout требует var и амперсанд.

Best practices

  • Подбирайте метки так, чтобы вызов читался как фраза: move(from:to:).
  • Используйте значения по умолчанию вместо нескольких перегрузок.
  • Применяйте inout редко и осознанно; чаще лучше вернуть новое значение.

Итоги. Функции структурируют логику. Метки аргументов и значения по умолчанию — фирменные черты Swift, делающие вызовы выразительными. Дальше мы превратим функции в значения — познакомимся с замыканиями.

Шире контекста

Культура именования в Swift заслуживает отдельного внимания, потому что Apple вложила в неё годы работы над гайдлайнами API Design Guidelines. Хорошее имя функции вместе с метками аргументов читается как грамотная английская или русская фраза в точке вызова: insert(item, at: index), move(from: source, to: destination). Это не педантизм — читаемая точка вызова экономит время каждому, кто потом будет разбираться в коде, включая вас самих через полгода. Значения по умолчанию избавляют от десятков перегрузок и делают API дружелюбным: вызывающий указывает только то, что отличается от обычного случая. Эти же принципы вы увидите во всём SwiftUI, где конструкторы вью щедро используют метки и значения по умолчанию. Поэтому, проектируя свои функции, думайте не только о теле, но и о том, как будет выглядеть и читаться их вызов — это половина хорошего API.

Проверьте себя
1. Зачем в Swift нужны метки аргументов (argument labels)?
AДля ускорения вычислений
BЧтобы вызов функции читался как фраза естественного языка
CОни обязательны для всех языков
DЧтобы скрыть параметры
2. Что нужно, чтобы функция могла изменить переданную переменную?
AПометить параметр как var
BИспользовать inout и передать аргумент через &
CВернуть Void
DОбъявить параметр через let