В функциональном программировании ссылочная прозрачность обычно означает, что выражение в коде может быть заменено результатом выполнения этого кода (или чем-либо, имеющим такое же значение), при этом результаты выполнения всего кода не изменятся. Это означает, что алгоритм всегда должен возвращать одно и то же значение для данного аргумента без какого-либо другого эффекта. Эта концепция функционального программирования также применима и к императивному программированию, и может помочь сделать код любого программиста более понятным. Мы подробно перевели статью “What Is Referential Transparency?” издания SitePoint и адаптировали примеры кода с Java (которая используется в оригинале) на JavaScript.
- Ссылочная прозрачность
- Ссылочная прозрачность в математике
- Ссылочная прозрачность в программировании
- Ссылочная прозрачность в императивном программировании
- Итог
Ссылочная прозрачность
Термин ссылочная прозрачность используется в математике, логике, лингвистике, философии и в программировании. В каждой из этих областей он имеет совершенно разные значения. Здесь мы будем иметь дело только с компьютерными программами, хотя и покажем аналогию с математикой (но не волнуйтесь — с достаточно простой математикой). Мы рассмотрим ссылочную прозрачность, используемую функциональными программистами.
Ссылочная прозрачность в математике
В математике ссылочная прозрачность — это свойство выражений, которые могут быть заменены другими выражениями, имеющими такое же значение, без какого-либо изменения результата. Рассмотрим следующий пример:
x = 2 + (3 * 4)
Мы можем заменить подвыражение (3 * 4)
любым другим выражением, имеющим то же значение, при этом не изменяя результат (значение x
). Наиболее очевидное выражение, которое следует использовать, конечно же 12
:
x = 2 + 12
При этом мы могли использовать любое другое выражение, имеющее значение 12
(возможно (5 + 7)
), не боясь изменения результата. Как следствие, часть этого выражения — (3 * 4)
, имеет ссылочную прозрачность.
Мы можем заменить и выражение 2 + 12
другим выражением, имеющим то же значение — так, чтобы оно оставалось ссылочно-прозрачным:
x = 14
Читайте также: Системы типов в языке — какие бывают и чем отличаются
Ссылочная прозрачность в программировании
В программировании ссылочная прозрачность применяется, соответственно, к программам. Поскольку они обычно состоят из подпрограмм, которые сами являются программами, это применимо и к этим подпрограммам. При этом они могут быть представлены в том числе и функциями. Это означает, что функции могут быть ссылочно-прозрачными — особенно когда вызов этих функций может быть заменен их возвращаемым значением.
const add = (a, b) => a + b;
const mult = (a, b) => a * b;
const x = add(2, mult(3, 4));
В этом примере функция mult
является ссылочно-прозрачной, потому что любой ее вызов может быть заменен соответствующим возвращаемым значением. Это можно увидеть, заменив mult(3, 4)
на 12
:
const x = add(2, 12);
Таким же образом add(2, 12)
можно заменить на возвращаемое значение 14
.
const x = 14;
Эти изменения не повлияют на результат работы программы, что бы она ни выполняла. Обратите внимание, что вообще мы могли бы использовать любое другое выражение, имеющее аналогичное значение — это свойство очень полезно при рефакторинге.
С другой стороны, рассмотрите следующую функцию:
const add = (a, b) => {
const result = a + b;
console.log(`Returning ${result}`);
return result;
};
Замена вызова функции add
возвращаемым значением изменит результат её работы, поскольку больше не будет печататься сообщение с помощью console.log
. В этом случае замена просто удалит побочный эффект, но в других случаях она может изменить значение, которое возвращается функцией.
const getFibsNext = () => {
let previous = -1;
let last = 1;
const next = () => {
last = previous + (previous = last);
return previous + last;
}
return next;
};
const printFibs = (limit) => {
const next = getFibsNext();
for (let i = 0; i < limit; i += 1) {
console.log(next());
}
};
printFibs(10);
Здесь функция next
не может быть заменена чем-либо, даже если оно имело бы такое же значение. Это связано с тем, что эта функция предназначена для возврата абсолютно разных значений при каждом вызове.
Использование таких не ссылочно-прозрачных функций требует особого внимания из-за изменяемого состояния, участвующего в вычислении. Функциональный стиль избегает таких функций в пользу их ссылочно-прозрачных версий.
Ссылочная прозрачность в императивном программировании
Функции используются как в императивном, так и в функциональном (декларативном) программировании. Несмотря на то, что функциональное программирование использует только функции, в императивном программировании также используются:
- Чистые функции: функции возвращающие значение, и не имеющие побочных эффектов.
- Чистые эффекты: функции, не возвращающие ничего, но изменяющие что-то снаружи.
- Функции с побочными эффектами: функции, возвращающие значение, и при этом изменяющие что-либо из вне.
Читайте также: DevOps — что это такое и почему эти практики меняют мир разработки уже сейчас
Как мы все знаем, рекомендуется избегать функций с побочными эффектами. Это оставляет императивным программистам возможность использовать или чистые функции, или чистые эффекты. Таким образом, ссылочная прозрачность является мощным инструментом для императивных программистов, который упрощает понимание программ, а также упрощает их тестирование.
Итог
Ссылочная прозрачность означает, что вызов функции может быть заменен ее значением, либо другим ссылочно-прозрачным вызовом с тем же результатом. Это делает каждую функцию независимой, что значительно упрощает модульное тестирование и рефакторинг. Кроме того, такие ссылочно-прозрачные функции легче читать и понимать — это одна из причин, почему код, написанный в функциональном стиле, нуждается в меньшем количестве комментариев.