В компьютерном программировании чистая функция является функцией со следующими свойствами:
Таким образом, чистая функция является вычислительным аналогом математической функции. Некоторые авторы, особенно из сообщества императивного языка, используют этот термин "чистые" для всех функций, которые имеют только указанное выше свойство 2 (обсуждается ниже).
Следующие примеры функций C ++ чистые:
floor
, возвращающие floor числа;max
, возвращает максимум из двух значений.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; }
sin ()
не является чистой, поскольку ее результат зависит от режима округления IEEE, который может быть изменен во время выполнения.int f (int * x) {return * x; }
void f () {static int x = 0; ++ x; }
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).
Поскольку чистые функции имеют одинаковое возвращаемое значение для тех же аргументов, они хорошо подходят для модульного тестирования.