Jump to content

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

В компьютерном программировании чистая функция это функция , обладающая следующими свойствами: [1] [2]

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

Примеры [ править ]

Чистые функции [ править ]

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

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

Нечистые функции [ править ]

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

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

Следующие функции 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;
      return x;
    }
    
  • из-за изменения возвращаемого значения в зависимости от входного потока и мутации входного потока
    int f() {
      int x = 0;
      std::cin >> x;
      return x;
    }
    

Ввод-вывод в чистых функциях [ править ]

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

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

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

Мемоизация [ править ]

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

Мемоизацию можно выполнить, обернув функцию в другую функцию ( функцию-обертку ). [5]

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

Программа C для кэшированного вычисления факториала ( assert() прерывается с сообщением об ошибке, если его аргумент ложный; на 32-битной машине значения выходят за рамки fact(12) все равно не может быть представлено. [ нужна ссылка ]

static int fact(int n) {
    return n<=1 ? 1 : fact(n-1)*n; 
}
int fact_wrapper(int n) {
    static int cache[13];
    assert(0<=n && n<13);
    if (cache[n] == 0)
        cache[n] = fact(n);
    return cache[n];
}

Оптимизация компилятора [ править ]

Функции, которые обладают только указанным выше свойством 2, то есть не имеют побочных эффектов, допускают методы оптимизации компилятора, такие как исключение общих подвыражений и оптимизация цикла , аналогичная арифметическим операторам. [6] Примером 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() вычисляется только один раз, перед циклом.

Некоторые языки программирования позволяют объявлять чистое свойство функции:

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

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

См. также [ править ]

Ссылки [ править ]

  1. ^ Бартош Милевский (2013). «Основы Хаскеля» . Школа Хаскеля . ФП завершено. Архивировано из оригинала 27 октября 2016 г. Проверено 13 июля 2018 г.
  2. ^ Брайан Лонсдорф (2015). «В основном адекватное руководство профессора Фрисби по функциональному программированию» . Гитхаб . Проверено 20 марта 2020 г.
  3. ^ Пейтон Джонс, Саймон Л. (2003). Язык Haskell 98 и библиотеки: пересмотренный отчет (PDF) . Кембридж, Соединенное Королевство: Издательство Кембриджского университета. п. 95. ИСБН  0-521 826144 . Проверено 17 июля 2014 г.
  4. ^ Ханус, Майкл. «Карри: интегрированный язык функциональной логики» (PDF) . www-ps.informatik.uni-kiel.de . Институт компьютерных наук Университета Кристиана Альбрехта в Киле. п. 33. Архивировано из оригинала (PDF) 25 июля 2014 года . Проверено 17 июля 2014 г.
  5. ^ Алей, Р. (2017). Профессиональное функциональное программирование на PHP: стратегии разработки приложений для оптимизации производительности, параллелизма, тестируемости и краткости кода . SpringerLink: Бюхер. Апресс. п. 109. ИСБН  978-1-4842-2958-3 . Проверено 4 февраля 2024 г.
  6. ^ «Атрибуты общих функций — использование коллекции компиляторов GNU (GCC)» . gcc.gnu.org, Коллекция компиляторов GNU . Фонд свободного программного обеспечения, Inc. Проверено 28 июня 2018 г.
  7. ^ Чистый атрибут в Фортране
  8. ^ Чистый атрибут на языке D
  9. ^ «Атрибуты общих функций» . Использование коллекции компиляторов GNU (GCC . Дата обращения 22 июля 2021 г. ).
  10. ^ атрибут constexpr в C++
Arc.Ask3.Ru: конец переведенного документа.
Arc.Ask3.Ru
Номер скриншота №: 4e02e933bff81ec379c32ba5f2a100f0__1717007940
URL1:https://arc.ask3.ru/arc/aa/4e/f0/4e02e933bff81ec379c32ba5f2a100f0.html
Заголовок, (Title) документа по адресу, URL1:
Pure function - Wikipedia
Данный printscreen веб страницы (снимок веб страницы, скриншот веб страницы), визуально-программная копия документа расположенного по адресу URL1 и сохраненная в файл, имеет: квалифицированную, усовершенствованную (подтверждены: метки времени, валидность сертификата), открепленную ЭЦП (приложена к данному файлу), что может быть использовано для подтверждения содержания и факта существования документа в этот момент времени. Права на данный скриншот принадлежат администрации Ask3.ru, использование в качестве доказательства только с письменного разрешения правообладателя скриншота. Администрация Ask3.ru не несет ответственности за информацию размещенную на данном скриншоте. Права на прочие зарегистрированные элементы любого права, изображенные на снимках принадлежат их владельцам. Качество перевода предоставляется как есть. Любые претензии, иски не могут быть предъявлены. Если вы не согласны с любым пунктом перечисленным выше, вы не можете использовать данный сайт и информация размещенную на нем (сайте/странице), немедленно покиньте данный сайт. В случае нарушения любого пункта перечисленного выше, штраф 55! (Пятьдесят пять факториал, Денежную единицу (имеющую самостоятельную стоимость) можете выбрать самостоятельно, выплаичвается товарами в течение 7 дней с момента нарушения.)