← Назад к вопросам

Может ли чистая функция завершиться с ошибкой?

2.0 Middle🔥 171 комментариев
#JavaScript Core

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI4 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Чистая функция и ошибки: парадокс в определении

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

Основные свойства чистой функции

Чистая функция определяется двумя ключевыми свойствами:

  1. Отсутствие побочных эффектов (No Side Effects): Функция не изменяет состояние программы вне своей локальной области — не меняет внешние переменные, не записывает в файл, не делает сетевые запросы.
  2. Определенность (Determinism): Для одних и тех же входных аргументов функция всегда возвращает один и тот же результат. Это свойство иногда называют идемпотентностью.

Возможность завершения с ошибкой: формальный взгляд

С формальной, теоретической точки зрения чистая функция не может "завершиться с ошибкой" в том смысле, который нарушает её определение.

Если функция при одинаковых аргументах иногда возвращает значение, а иногда выбрасывает исключение, она нарушает принцип определенности. Для аргумента x в момент t1 мы получили результат y, а в момент t2 — исключение Error. Это разные выходные данные, что делает функцию нечистой.

// Пример НЕчистой функции: результат зависит от внешнего состояния (randomNumber)
function unstableDivision(a, b) {
  const randomNumber = Math.random(); // Внешнее состояние!
  if (randomNumber > 0.5) {
    return a / b;
  } else {
    throw new Error('Random failure!'); // Недетерминированное поведение
  }
}

Практическая реализация в языках программирования

На практике, в языках типа JavaScript, Java или Python, чистые функции могут и часто завершаются с ошибками, но это не нарушает их чистоту, если ошибка является частью их детерминированного результата.

Ключевое понимание: В контексте языка, исключение (или ошибка) — это просто альтернативный, но детерминированный результат функции для определенных входных данных. Например, функция проверки делимости:

// Чистая функция, которая может выбросить исключение
function pureDivide(a, b) {
  if (b === 0) {
    throw new Error('Division by zero'); // Для входных (a, 0) результат всегда один: это исключение
  }
  return a / b;
}

// Вызовы: результат детерминирован для одинаковых аргументов
console.log(pureDivide(10, 2)); // Всегда 5
console.log(pureDivide(10, 0)); // Всегда Error('Division by zero')

Для аргументов (10, 0) функция всегда и однозначно вернет экземпляр Error с сообщением 'Division by zero'. Это удовлетворяет условию детерминированности. Побочных эффектов также нет.

Моделирование ошибок как части возвращаемого значения

В строгих функциональных языках (Haskell, Elm) подход часто другой. Ошибки моделируются как часть возвращаемого типа, используя структуры типа Maybe (Значение или Ничего) или Either (Результат или Ошибка).

-- Пример на Haskell: чистый результат с типом Either
safeDivide :: Double -> Double -> Either String Double
safeDivide a b =
  if b == 0
    then Left "Division by zero"  -- Ошибка как левое значение
    else Right (a / b)            -- Успех как правое значение

В этом случае функция никогда "завершается с ошибкой" в смысле неконтролируемого исключения. Она всегда возвращает значение типа Either, которое явно содержит информацию об успехе или неудаче. Это сохраняет чистоту на 100%.

Итог и важное разграничение

Таким образом, ответ можно сформулировать так:

  • В идеальной, теоретической модели чистая функция — это математическое отображение входов на выходы. "Ошибка" не является элементом этого отображения, поэтому чистая функция не должна её генерировать. Все возможные случаи должны быть частью её возвращаемого типа.
  • В практических императивных и гибридных языках (JavaScript, Python) чистая функция может вызывать исключения, если эти исключения являются детерминированной и неизменной реакцией на конкретные входные данные. Например, валидация аргументов: для невалидного аргумента функция всегда бросит одинаковую ошибку. Это не делает её нечистой.
  • Однако лучшей практикой, особенно в функциональном стиле, считается предотвращение исключений как контролируемого потока и использование специальных возвращаемых типов (Result, Either, объекты с { success, data, error }) для явного представления возможных неудач. Это делает код более предсказуемым, композируемым и легко тестируемым.

Следовательно, в контексте современной фронтенд-разработки на JavaScript можно сказать: чистая функция может завершиться с ошибкой (выбросить исключение), но только если эта ошибка является её единственным и неизменным "результатом" для заданного невалидного входного состояния. Но более чистый и надежный подход — избегать исключений как механизма обработки ожидаемых ошибок и моделировать их в возвращаемом значении.

Может ли чистая функция завершиться с ошибкой? | PrepBro