В компьютерном программировании , А чистая функция является функцией , которая обладает следующими свойствами: [1] [2]
- Эти функции возвращаемых значения являются идентичными для идентичных аргументов (без изменения с локальным переменными статическим , нелокальными переменным , изменяемыми опорными аргументами или входными потоками ).
- Функции приложения не имеет побочных эффектов (нет мутации локальных переменных статических, нелокальных переменных, изменяемых опорных аргументов или ввода / вывода потоков).
Таким образом, чистая функция является вычислительным аналогом математической функции . Некоторые авторы, особенно из сообщества императивных языков, используют термин «чистые» для всех функций, которые имеют только указанное выше свойство 2 [3] [4] (обсуждается ниже ).
Примеры [ править ]
Чистые функции [ править ]
Следующие примеры функций C ++ являются чистыми:
void f () { статический std :: atomic < unsigned int > x = 0 ; ++ x ; }
- Хотя этот пример кода выглядит не чистым, на самом деле это так. Значение
x
можно наблюдать только внутри других вызововf()
, и, посколькуf()
оно не передает значениеx
в свою среду, оно неотличимо от функцииvoid f() {}
, которая ничего не делает. Следует отметить , чтоx
этоstd::atomic
так , что модификации из нескольких потоков , исполняющихf()
одновременно не приводят в гонке данных , которая имеет неопределенное поведение в C и C ++.
Нечистые функции [ править ]
Следующие функции C ++ являются нечистыми, поскольку у них отсутствует указанное выше свойство 1:
- из-за изменения возвращаемого значения со статической переменной
int f () { статический int x = 0 ; ++ x ; вернуть x ; }
- из-за изменения возвращаемого значения с нелокальной переменной
int f () { вернуть х ; }
- По той же причине, например, функция библиотеки C ++
sin()
не является чистой, поскольку ее результат зависит от режима округления IEEE, который можно изменить во время выполнения.
- из-за изменения возвращаемого значения с изменяемым ссылочным аргументом
int f ( int * x ) { return * x ; }
- из-за изменения возвращаемого значения с входным потоком
int f () { int x = 0 ; std :: cin >> x ; вернуть x ; }
Следующие функции C ++ являются нечистыми, поскольку у них отсутствует указанное выше свойство 2:
- из-за мутации локальной статической переменной
void f () { static int x = 0 ; ++ x ; }
- из-за мутации нелокальной переменной
void f () { ++ x ; }
- из-за мутации изменяемого ссылочного аргумента
недействительно f ( int * x ) { ++ * x ; }
- из-за мутации выходного потока
void f () { std :: cout << "Привет, мир!" << std :: endl ; }
Следующие функции C ++ являются нечистыми, поскольку в них отсутствуют оба указанных выше свойства 1 и 2:
- из-за изменения возвращаемого значения с локальной статической переменной и мутации локальной статической переменной
int f () { статический int x = 0 ; ++ x ; вернуть x ; }
- из-за изменения возвращаемого значения с входным потоком и мутации входного потока
int f () { int x = 0 ; std :: cin >> x ; вернуть x ; }
Ввод / вывод в чистых функциях [ править ]
Ввод-вывод по своей сути нечист: операции ввода подрывают ссылочную прозрачность , а операции вывода создают побочные эффекты. Тем не менее, есть смысл, в котором функция может выполнять ввод или вывод и при этом оставаться чистой, если последовательность операций на соответствующих устройствах ввода-вывода моделируется явно как аргумент и результат, а операции ввода-вывода принимаются в завершиться ошибкой, если входная последовательность не описывает операции, фактически выполненные с момента начала выполнения программы.
Второй пункт гарантирует, что единственная последовательность, используемая в качестве аргумента, должна изменяться с каждым действием ввода-вывода; первый позволяет различным вызовам функции, выполняющей ввод-вывод, возвращать разные результаты из-за изменения аргументов последовательности. [5] [6]
Монада ввода / вывода является идиома программирования обычно используется для выполнения ввода / вывода в чистых функциональных языках.
Оптимизация компилятора [ править ]
Функции, которые имеют только указанное выше свойство 2, позволяют использовать методы оптимизации компилятора, такие как устранение общих подвыражений и оптимизацию цикла, аналогичную арифметическим операторам. [3] Примером C ++ является length
метод, возвращающий размер строки, который зависит от содержимого памяти, на которое указывает строка, поэтому в нем отсутствует указанное выше свойство 1. Тем не менее, в однопоточной среде следующий код C ++
std :: string s = "Привет, мир!" ; int a [ 10 ] = { 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 }; int l = 0 ;для ( int i = 0 ; i < 10 ; ++ i ) { l + = s . длина () + а [ я ]; }
можно оптимизировать так, чтобы значение s.length()
вычислялось только один раз перед циклом.
В Fortran , то pure
ключевое слово может быть использовано , чтобы объявить функцию , чтобы быть просто побочным эффектом бесплатно (т.е. иметь только указанное свойство 2).
Модульное тестирование [ править ]
Поскольку чистые функции имеют одинаковые возвращаемые значения для одинаковых аргументов , они хорошо подходят для модульного тестирования .
См. Также [ править ]
- Выполнение функции во время компиляции: оценка чистых функций во время компиляции
- Детерминированный алгоритм
- Чисто функциональная структура данных
- Лямбда-исчисление
- Побочный эффект (информатика)
- Чистая процедура
- Идемпотентность
- ключевое слово pure в Фортране, аннотирующее чистые функции
- Ключевое слово constexpr в C ++, аннотирующее чистые функции, которые можно использовать во время компиляции
Ссылки [ править ]
- ^ Бартош Milewski (2013). «Основы Haskell» . Школа Haskell . FP Complete. Архивировано из оригинала на 2016-10-27 . Проверено 13 июля 2018 .
Вот основные свойства чистой функции: 1. Функция возвращает один и тот же результат каждый раз, когда она вызывается с одним и тем же набором аргументов. Другими словами, функция не имеет состояния и не может получить доступ к какому-либо внешнему состоянию. Каждый раз, когда вы его называете, он ведет себя как новорожденный ребенок с пустой памятью и незнанием внешнего мира. 2. Функция не имеет побочных эффектов. Один раз вызвать функцию - это то же самое, что вызвать ее дважды и отбросить результат первого вызова.
- ^ Брайан Лонсдорф (2015). "Практически адекватное руководство профессора Фрисби по функциональному программированию" . GitHub . Проверено 20 марта 2020 .
Чистая функция - это функция, которая при одном и том же вводе всегда будет возвращать один и тот же вывод и не имеет наблюдаемых побочных эффектов.
- ^ a b «Руководство GCC 8.1» . GCC, Коллекция компиляторов GNU . Фонд свободного программного обеспечения, Inc. 2018 . Проверено 28 июня 2018 .
- ^ Возможности языка Fortran 95 # Чистые процедуры
- ^ Пейтон Джонс, Саймон Л. (2003). Язык и библиотеки Haskell 98: исправленный отчет (PDF) . Кембридж, Соединенное Королевство: Издательство Кембриджского университета. п. 95. ISBN 0-521 826144. Проверено 17 июля 2014 года . CS1 maint: обескураженный параметр ( ссылка )
- ^ Hanus, Майкл. «Карри: интегрированный функциональный логический язык» (PDF) . www-ps.informatik.uni-kiel.de . Institut für Informatik, Christian-Albrechts-Universität zu Kiel. п. 33. Архивировано из оригинального (PDF) 25 июля 2014 года . Проверено 17 июля 2014 года . CS1 maint: обескураженный параметр ( ссылка )
Внешние ссылки [ править ]
- Чистый атрибут в Фортране
- Атрибут constexpr в C ++
- Чистый атрибут на языке D