Прозорість посилань (інформатика)

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

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

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

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

Через те, що прозорість посилань вимагає однакового результату на однаковому вході в будь-який час, прозорий по посиланнях вираз є детермінованим за визначенням.

Приклади й контрприклади[ред.ред. код]

Якщо в виразі задіяні лише чисті функції, тоді вираз буде прозорим по посиланнях. Також, деякі нечисті функції можуть бути використані в виразі, якщо їх значення не впливають на значення виразу та їх побічні ефекти незначимі.

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

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

Арифметичні операції прозорі по посиланнях: 5*5 можна замінити на 25. В дійсності, всі функції прозорі по посиланнях в математичному сенсі: sin(x) прозора, бо вона завжди повертає те саме значення для певного x.

Присвоєння не прозоре. Наприклад, вираз на C x = x + 1 змінює значення надане x. Припустимо x початково має значення 10, два послідовні обчислення виразу дають, відповідно, 11 і 12. Звідси видно, що заміна x = x + 1 на 11 або 12 надасть програмі іншого енсу, отже вираз не прозорий по посиланнях. Однак, виклик функції int plusone(int x) {return x+1;} є прозорим, бо вона явно не змінює x отже не має побічних ефектів.

В більшості мов, print("Вітаю, світе!") не прозора, бо заміна її на значення, що вона повертає змінює поведінку програми, бо «Вітаю, світе!» не надрукується.

today() теж не прозора, бо видає різні значення кожного нового дня.

Відмінність від імперативного програмування[ред.ред. код]

Якщо заміна виразу на його значення чинна тільки в певній точці виконання програми, тоді цей вираз не прозорий по посиланнях. Визначення і впорядкування цих точок перебігу (англ. sequence point) це теоретичні підвалини імперативного програмування і частина семантики імперативних мов програмування.

Однак, через можливість обчислення виразів прозорих по посиланнях будь-коли, необов'язково визначати точки перебігу й взагалі будь-які гарантії послідовності виконання. Програмування виконане на такий штиб називається чисто функційним програмуванням.

Однією з переваг написання коду з прозорими посиланнями є те, що розумному компілятору легше виконувати статичний розбір коду і використовувати кращі оптимізації. Наприклад, у випадку С присутнє погіршення швидкодії через додавання до тіла циклу дорогої, в сенсі виконання, функції, навіть якщо виклик функції можна винести за тіло циклу без зміни результату програми. Програміст змушений робити ручні правки, які можливо позначаться на зручночитності коду. А якщо компілятор в змозі визначити, що виклик функції прозорий по посиланнях, він може здійснити це перетворення автоматично.

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

У випадку прозорості посилань, немає різниці між посиланням на об'єкт і самим об'єктом. Інакше така різниця може бути легко введена й використана.