«Нормальный» способ сформулировать, что такое чистая функция , - это ссылочная прозрачность . Функция чиста, если она прозрачна по ссылкам .
Ссылочная прозрачность , грубо говоря, означает, что вы можете заменить вызов функции ее возвращаемым значением или наоборот в любой точке программы, не изменяя смысла программы.
Так, например, если 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
массив. Тем не менее, мы можем рассмотреть функцию и можно увидеть , что она является референциально прозрачной и таким чистой. Иногда это называют внешней чистотой. , т. Е. Функцией, которая кажется чистой внешнему миру, но реализуется нечистой внутри.
Такие функции по-прежнему полезны, потому что, хотя примесь заражает все вокруг себя, внешний чистый интерфейс создает своего рода «барьер чистоты», где примесь заражает только три строки функции, но не просачивается в остальную часть программы. . Эти три строки намного легче проанализировать на правильность, чем всю программу.