Программирование SwiftSwift CoreМладший Swift-разработчик

Функция возвращает результат, который вызывающий код намеренно игнорирует: как в Swift выразить это намерен...

Функция возвращает результат, который вызывающий код намеренно игнорирует: как в Swift выразить это намерение без предупреждения компилятора?

Проходите собеседования с ИИ помощником Hintsage

Краткий ответ

Для этого объявление функции помечают атрибутом @discardableResult. Swift перестаёт предупреждать, если вызывающий код не использует возвращаемое значение, но сама функция по-прежнему возвращает его и не меняет семантику вызова.

Исторический контекст

Swift по умолчанию предупреждает об игнорировании результата функции, потому что это часто означает ошибку: например, вызывающий код мог забыть проверить статус операции или сохранить созданное значение. Атрибут @discardableResult нужен для API, где результат полезен не всегда, а побочный эффект вызова является самостоятельной целью.

Подход разделяет два намерения: случайное игнорирование результата считается подозрительным, а намеренное — явно отмечается в объявлении функции и становится частью её контракта.

Постановка проблемы

Без специальной пометки вызов функции с неиспользованным возвращаемым значением обычно приводит к предупреждению компилятора. Это не ошибка выполнения и не мешает запуску программы, но такие предупреждения могут скрывать действительно важные места, где результат был случайно проигнорирован.

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

Подробное решение

Атрибут @discardableResult ставят перед объявлением функции или метода. Он сообщает компилятору, что отсутствие использования возвращаемого значения является допустимым сценарием.

@discardableResult func recordEvent(_ name: String) -> Bool { print("Записано: \(name)") return true } recordEvent("Запуск") let wasRecorded = recordEvent("Завершение") print(wasRecorded)

В первом вызове результат намеренно отброшен без предупреждения, а во втором сохранён и использован. Атрибут не заставляет функцию выполнять побочный эффект, не меняет тип результата, не делает его необязательным и не отключает другие диагностики компилятора.

Без @discardableResult результат можно явно отбросить в конкретном месте с помощью присваивания специальному идентификатору _. Это более локальное решение: оно показывает намерение именно для данного вызова, а не для всех пользователей функции.

Главный компромисс связан с безопасностью API. Пометка удобна для методов вроде регистрации события, обновления состояния или отправки команды, но опасна для функций, чей результат содержит ошибку, созданный объект или обязательный статус операции: предупреждение может быть полезной защитой от неправильного использования.

Ситуация из практики

В SDK есть метод регистрации аналитического события. Он возвращает логический результат, показывающий, удалось ли поставить событие в очередь, но большинство вызывающих мест лишь отправляют событие и не проверяют этот статус.

Можно оставить функцию без атрибута и заставить каждый вызов явно обрабатывать или отбрасывать результат. Это сохраняет строгую проверку, но добавляет шум в местах, где результат действительно не нужен. Другой вариант — изменить функцию так, чтобы она ничего не возвращала; тогда теряется возможность проверить результат там, где это важно.

Выбранное решение — @discardableResult, если игнорирование результата допустимо по контракту для всех вызовов. В критичных участках результат сохраняют и проверяют. Если же успешность отправки обязательна для корректности операции, атрибут применять не следует: предупреждение должно подталкивать разработчика к обработке результата.

Что кандидаты часто упускают

  1. Вопрос: Меняет ли @discardableResult поведение функции во время выполнения?

    Ответ: Нет. Это атрибут для диагностики на этапе компиляции. Функция всё равно вычисляет и возвращает значение, а её побочные эффекты происходят так же, как без атрибута. Меняется только реакция компилятора на неиспользованный результат.

  2. Вопрос: Чем локальное присваивание результата _ отличается от @discardableResult?

    Ответ: Присваивание _ явно отбрасывает результат одного конкретного вызова. Атрибут разрешает отбрасывать результат во всех местах использования функции, поэтому он является более широким обещанием автора API. Если игнорирование допустимо лишь в отдельных сценариях, локальное присваивание безопаснее.

  3. Вопрос: Можно ли с помощью @discardableResult скрыть предупреждение о том, что функция возвращает ошибку?

    Ответ: Технически атрибут убирает предупреждение об игнорировании результата, но это не делает игнорирование корректным. Если результат содержит информацию об ошибке или необходим для продолжения операции, пометка ухудшает защиту API и может привести к незаметной потере ошибки. В таком случае лучше требовать явную обработку результата или выбрать другой интерфейс функции.