Чистые и эффективные функции: Введение
January 5, 2021
В этом блоге и своей книге я постоянно повторяю мантру о "разделении эффектов и логики" и поэтому мне необходимо, чтобы читатели однозначно меня понимали. Однако когда я начал разбирать существующую терминологию, с удивлением обнаружил, что общепринятой вообще нет, а те варианты что есть не отражают важных мне нюансов. Поэтому я решил написать цикл статей об используемой мной терминологии.
С чистыми функциями всё более-менее просто, у них на вики есть внятное определение:
это функция, которая:
- является детерминированной;
- не обладает побочными эффектами.
Хотя и тут уже есть пара нюансов - на русской вики ссылок вообще нет, английская ссылается на пару случайных книг. Плюс определение даётся через побочные эффекты (они же сайдэффекты).
Ладно давайте посмотрим что такое сайдэффекты на той же вики:
любые действия работающей программы, изменяющие среду выполнения (англ. execution environment). Например, к побочным эффектам относятся:
- доступ (чтение или запись) к объекту, определённому с модификатором volatile (англ.);
- изменение (запись) объекта;
- изменение файла;
- изменение поведения инструкций процессора, обрабатывающих числа с плавающей точкой (см. floating-point environment (англ.));
- вызов функции, выполняющей любое из перечисленных выше действий.
И вот тут уже возникают вопросы. Смотрю я на примеры и вроде всё правильно, но что-то с ними не то. Но если взглянуть на ссылку откуда они взяты: The Art of Software Security Assessment: Identifying and Preventing Software Vulnerabilities, то всё становится на свои места. Ток спрашивается при чём тут секьюрити?
Ок, может на английском получше?
In computer science, an operation, function or expression is said to have a side effect if it modifies some state variable value(s) outside its local environment, that is to say has an observable effect besides returning a value (the main effect) to the invoker of the operation. […] Example side effects include modifying a non-local variable, modifying a static local variable, modifying a mutable argument passed by reference, performing I/O or calling other side-effect functions.
Тут уже получше, но всё равно возникает ряд вопросов.
И самый главный - эффект побочный чему?
Вычислению?
А если я вызываю функцию только ради ""побочного" эффекта?
printf
, например - он тоже побочный?
Кажется, что помимо побочных эффектов должны существовать и просто эффекты.
Другой вопрос - что между чистыми функциями и функциями с сайд эффектами? Например функция чтения текущего времени. Или функция возвращающая значение глобальной переменной? Они недетерминированные, т.е. не чистые, и не менют глобальное состояние, т.е. без сайд эффектов по версии вики.
При желании можно нагуглить текстом и видео понятие функционального эффекта и эффективной функции.
Но там начинается веселуха - говорят, что эффект, это то, как монада реализует свой flatMap. И записывают в эффекты, помимо того что вики записывает в сайд эффекты, и мои функции читающие глобальное состояние, ещё и эффект асинхронности (Future), ошибки (Try) и даже отсутствия значения (Option). Эффективными функциями называют функции, которые вместо результата типа T, возвращают какую-то обёртку вокруг этого результата F. А сайд эффект - это вообще баг.
Вот такую удручающую картину на данный момент представляет из себя терминология эффектов. Но в этом цикле статей я представлю вам свою согласованную и полную терминологию:)
Книга в тему: Concepts of Programming Languages - раздел 7.2.2