Чистая функция

редактировать

В компьютерном программировании чистая функция является функцией со следующими свойствами:

  1. Его возвращаемое значение одинаково для тех же аргументов (без изменений с локальными статическими переменными, без -локальные переменные, изменяемые ссылочные аргументы или входные потоки от устройств ввода-вывода ).
  2. Его оценка не имеет побочных эффектов (нет мутации локальных статических переменных, нелокальные переменные, изменяемые ссылочные аргументы или потоки ввода-вывода).

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

Содержание
  • 1 Примеры
    • 1.1 Чистые функции
    • 1.2 Неочищенные функции
  • 2 I / O в чистых функциях
  • 3 Оптимизация компилятора
  • 4 Модульное тестирование
  • 5 См. Также
  • 6 Ссылки
  • 7 Внешние ссылки
Примеры

Чистые функции

Следующие примеры функций C ++ чистые:

  • floor, возвращающие floor числа;
  • max, возвращает максимум из двух значений.
  • функция f, определенная как
void f () {static std :: атомарный x = 0; ++ x; }
Хотя этот пример кода выглядит не чистым, на самом деле это так. Значение xможно наблюдать только внутри других вызовов f (), и поскольку f ()не передает значение xдля своей среды, она неотличима от функции void f () {}, которая ничего не делает. Обратите внимание, что x- это std :: atomic, поэтому изменения из нескольких потоков, выполняющих f ()одновременно, не приводят к гонке данных, который имеет неопределенное поведение в C и C ++.

Неочищенные функции

Следующие функции C ++ являются нечистыми, поскольку у них отсутствует указанное выше свойство 1:

  • из-за изменения возвращаемого значения с нелокальная переменная
int f () {return x; }
По той же причине, например, функция библиотеки C ++ sin ()не является чистой, поскольку ее результат зависит от режима округления IEEE, который может быть изменен во время выполнения.
  • из-за изменения возвращаемого значения с изменяемым ссылочный аргумент
int f (int * x) {return * x; }
  • из-за несовместимого определенного / неопределенного поведения:
void f () {static int x = 0; ++ x; }
Переполнение целого числа со знаком - это неопределенное поведение согласно спецификации C ++. Кроме того, если f ()вызывается одновременно, код демонстрирует гонку данных. Чистые функции могут давать сбой или никогда не возвращаться, но они должны делать это последовательно (для одного и того же входа). Однако f ()может или не может дать сбой, в зависимости от того, была ли достигнута верхняя граница разрешенного значения signed intили произошла гонка данных, или нет.

Следующие функции C ++ являются нечистыми, поскольку у них отсутствует указанное выше свойство 2:

  • из-за мутации локальной статической переменной
void f () {static int x = 0; ++ x; }
  • из-за мутации нелокальной переменной
void f () {++ x; }
  • из-за мутации изменяемого ссылочного аргумента
void f (int * x) {++ * x; }
  • из-за мутации выходного потока
void f () {std :: cout << "Hello, world!" << std::endl; }

Следующие функции C ++ являются нечистыми, поскольку у них отсутствуют оба вышеуказанных свойства 1 и 2:

  • из-за возвращаемого значения изменение с локальной статической переменной и изменение локальной статической переменной
int f () {static int x = 0; ++ x; вернуть x; }
  • из-за вариации возвращаемого значения с входным потоком и мутации входного потока
int f () {int x = 0; std :: cin>>x; вернуть x; }
Ввод-вывод в чистых функциях

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

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

монада ввода-вывода - это идиома программирования обычно используется для ввода-вывода на чисто функциональных языках.

Оптимизация компилятора

Функции, которые имеют только указанное выше свойство 2, позволяют использовать методы оптимизации компилятора, такие как исключение общего подвыражения и оптимизация цикла, аналогичная арифметической операторы. Примером C ++ является метод length, возвращающий размер строки, который зависит от содержимого памяти, на которое указывает строка, поэтому в нем отсутствует указанное выше свойство 1. Тем не менее, в однопоточном среда, следующий код C ++

std :: string s = "Hello, world!"; int a [10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; int l = 0; for (int i = 0; i < 10; ++i) { l += s.length() + a[i]; }

можно оптимизировать таким образом, чтобы значение s.length ()вычислялось только один раз перед циклом.

В Fortran, ключевое слово pureможно использовать для объявления функции, которая не имеет побочных эффектов (т.е. имеет только указанное выше свойство 2).

Модульное тестирование

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

См. Также
Ссылки
Внешние ссылки
Последняя правка сделана 2021-06-02 11:01:14
Содержание доступно по лицензии CC BY-SA 3.0 (если не указано иное).
Обратная связь: support@alphapedia.ru
Соглашение
О проекте