В чем разница между @autoclosure и обычным замыканием в Swift?

«В чем разница между @autoclosure и обычным замыканием в Swift?» — вопрос из категории Swift Core, который задают на 10% собеседований IOS Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Разница заключается в синтаксисе вызова и автоматическом преобразовании выражения в замыкание.

Аспект Обычное замыкание @autoclosure
Синтаксис передачи Требует явного указания замыкания { ... }. Позволяет передать простое выражение без {}.
Цель Явная передача исполняемого блока кода. Синтаксический сахар для отложенного вычисления выражений.
Вычисление Может быть как немедленным, так и отложенным (зависит от реализации). Всегда отложенное — выражение вычисляется только при вызове замыкания внутри функции.

Сравнение на примере:

// 1. Функция с обычным замыканием
func executeNormal(closure: () -> Bool) {
    if closure() { print("Normal: True") }
}
// Вызов ТРЕБУЕТ фигурных скобок
executeNormal(closure: { 2 > 1 })

// 2. Функция с autoclosure
func executeAuto(_ condition: @autoclosure () -> Bool) {
    if condition() { print("Auto: True") }
}
// Вызов БЕЗ фигурных скобок — выражение обернуто автоматически
executeAuto(2 > 1)

Практическое применение @autoclosure:

  • Оператор объединения по nil (??): Правый операнд вычисляется только если левый — nil.
    let value = optionalValue ?? calculateDefault() // calculateDefault() вызовется только если optionalValue == nil
  • Логические операторы &&, ||: Правый операнд вычисляется только при необходимости (short-circuit evaluation).
  • Условные проверки (assert, precondition): Затратные вычисления для отладочных сообщений выполняются только в отладочных конфигурациях.

Итог: @autoclosure — это инструмент для создания более чистого API в случаях, где логика требует передачи выражения для его потенциально отложенного вычисления.