Побічний ефект (програмування)

Матеріал з Вікіпедії — вільної енциклопедії.
Перейти до навігації Перейти до пошуку

Функція або вираз мають побічний ефект, якщо, на додаток до повернення значення, вони змінюють якийсь стан програми або проводять видиму взаємодію з викликальною функцією або зовнішнім світом. Наприклад, функція може змінювати глобальну або статичну змінну, змінювати один зі своїх аргументів, спричиняти виняткову ситуацію, виводити дані на пристрій виведення або у файл, читати дані або викликати інші функції з побічними ефектами. За наявності побічних ефектів, поведінка програми залежить від історії; тобто порядок обчислень має значення. Розуміння програми з побічними ефектами вимагає знання про контекст та історію; навіть при наявності цих знань важко добрати перебіг програми, а також зневадити її.[1][2]

Побічні ефекти — найзвичніший спосіб взаємодії з зовнішнім світом (людьми, файловою системою, іншими комп'ютерами в мережі). Ступінь використання побічних ефектів залежить від парадигми програмування. Імперативне програмування відоме частим використанням побічних ефектів. У функціональному програмуванні побічні ефекти використовують зрідка. Функціональні мови такі як Standard ML або Scheme не забороняють побічні ефекти, але зазвичай програмісти уникають їх.[3] Функціональна мова Haskell обмежує побічні ефекти через статичну систему типізації; вона використовує концепцію монад.[4][5]

Розробники на мові асемблера мають зважати на приховані побічні ефекти — інструкції, які змінюють частину стану процесора без зазначення цього в своїх назвах. Класичний приклад прихованого побічного ефекту — арифметична інструкція, яка явно змінює регістр (явний ефект (англ. overt effect)) і неявно змінює коди умов (прихований побічний ефект). Наприклад, прапорці, що вказують на те, що в результаті отримано нуль або переповнення. Один з недоліків набору інструкцій з багатьма побічними ефектами полягає в можливості впливу на одну частинку стану, наприклад коди умов, тоді коли вимога оновлювати ці стани послідовно може стати вузьким місцем швидкодії. Проблема постає особливо гостро на процесорах розроблених з конвеєром команд (з 1990) або з позачерговим виконанням. Такі процесори можуть потребувати додаткову схему для перевірки на побічні ефекти і зупиняти конвеєр, якщо наступна інструкція залежить від наслідків цих ефектів.

Прозорість посилань[ред. | ред. код]

Відсутність побічних ефектів є необхідною, але не достатньою умовою для прозорості посилань. Прозорість посилань значить, що вираз (такий як виклик функції) може бути заміненим на його значення; для цього необхідно, щоб вираз не тільки не мав побічних ефектів, але й був чистим (завжди повертав той самий результат для одних вхідних даних).

Часові побічні ефекти[ред. | ред. код]

На побічні ефекти, пов'язані з часом необхідним для виконання дії, зазвичай не зважають, коли йдеться про побічні ефекти або прозорість посилань. В більшості програм бажано замінювати довгі дії на коротші, наприклад, (60 / 3 * 2) на 40. Іноді, коли йдеться про синхронізацію або тестування, зумисне вставляються такі коди, що мають часовий побічний ефект, наприклад, Sleep(5000) або for(i=0; i < 10000; i++){}. Ці інструкції не змінюють стан окрім потреби очікування до їх завершення.

Ідемпотентність[ред. | ред. код]

Функція без побічних ефектів f завжди ідемпотентна (в розумінні послідовних викликів f; f, але не композиції функцій ff).

Примітки[ред. | ред. код]

  1. «Research Topics in Functional Programming» ed. D. Turner, Addison-Wesley, 1990, pp 17–42. Retrieved from: Hughes, John. Why Functional Programming Matters (PDF). 
  2. Collberg. CSc 520 Principles of Programming Languages. Department of Computer Science, University of Arizona. 
  3. Matthias Felleisen. How To Design Programs. MIT Press. 
  4. Haskell 98 Library Report: Input/Output. 
  5. Imperative Functional Programming, Simon Peyton Jones and Phil Wadler, Conference Record of the 20th Annual ACM Symposium on Principles of Programming Languages, pages 71–84, 1993

Джерела[ред. | ред. код]