«Нормальный» способ сформулировать, что такое чистая функция , - это ссылочная прозрачность . Функция чиста, если она прозрачна по ссылкам .
Ссылочная прозрачность , грубо говоря, означает, что вы можете заменить вызов функции ее возвращаемым значением или наоборот в любой точке программы, не изменяя смысла программы.
Так, например, если C printfбыли ссылочно прозрачными, эти две программы должны иметь одинаковое значение:
printf("Hello");
и
5;
и все следующие программы должны иметь одно и то же значение:
5 + 5;
printf("Hello") + 5;
printf("Hello") + printf("Hello");
Потому как printf возвращает количество написанных символов, в данном случае 5.
С voidфункциями это становится еще более очевидным . Если у меня есть функция void foo, то
foo(bar, baz, quux);
должно быть таким же, как
;
Т.е. поскольку fooничего не возвращает, я должен иметь возможность заменить его ничем, не меняя смысла программы.
Таким образом, ясно, что ни одно из них, printfни fooявляется референциально прозрачным, и, следовательно, ни одно из них не является чистым. Фактически, voidфункция никогда не может быть ссылочно прозрачной, если только она не является нерабочей.
Я считаю, что это определение намного проще, чем то, которое вы дали. Он также позволяет вам применять его с любой степенью детализации: вы можете применять его к отдельным выражениям, функциям и целым программам. Это позволяет, например, говорить о такой функции:
func fib(n):
return memo[n] if memo.has_key?(n)
return 1 if n <= 1
return memo[n] = fib(n-1) + fib(n-2)
Мы можем проанализировать выражения, составляющие функцию, и легко прийти к выводу, что они не являются ссылочно прозрачными и, следовательно, не являются чистыми, поскольку они используют изменяемую структуру данных, а именно memoмассив. Тем не менее, мы можем рассмотреть функцию и можно увидеть , что она является референциально прозрачной и таким чистой. Иногда это называют внешней чистотой. , т. Е. Функцией, которая кажется чистой внешнему миру, но реализуется нечистой внутри.
Такие функции по-прежнему полезны, потому что, хотя примесь заражает все вокруг себя, внешний чистый интерфейс создает своего рода «барьер чистоты», где примесь заражает только три строки функции, но не просачивается в остальную часть программы. . Эти три строки намного легче проанализировать на правильность, чем всю программу.