Могут ли чистые функции читать глобальное состояние?
Обратите внимание: под "чистой" функцией я не подразумеваю "чисто виртуальную"
Я имею в виду это
Если функция "читает" некое глобальное состояние, автоматически ли это делает его нечистым? или это зависит от других факторов?
Если он автоматически делает его нечистым, объясните, почему.
Если это зависит от других факторов, поясните, чем они являются.
4 ответа
"Чистая" функция - это функция, результат которой зависит только от входных аргументов. Если он читает что-то еще, это не чистая функция.
В определенных специализированных случаях, да. Например, если бы у вас был глобальный кэш уже вычисленных значений, которые были прочитаны и записаны только вашей функцией, он все равно был бы математически чистым, в том смысле, что выходные данные зависели только от входных данных, но не были бы чистыми в самом строгом смысле. Например:
static int cache[256] = {0};
int compute_something(uint8_t input)
{
if(cache[input] == 0)
cache[input] = (perform expensive computation on input that won't return 0);
return cache[input];
}
В этом случае, пока никакая другая функция не касается глобальной cache
, это все еще математически чистая функция, хотя технически она зависит от внешнего глобального состояния. Тем не менее, это состояние просто оптимизация производительности - без него оно все равно будет выполнять те же вычисления, только медленнее.
Например, в Haskell вы можете создать бесконечный список случайных чисел на нечистой стороне и передать этот список вашей чистой функции. Реализация сгенерирует следующее число, которое ваша чистая функция использует только тогда, когда это необходимо, но функция все еще чиста.
Чистые функции необходимы для построения чистых выражений. Постоянные выражения являются чистыми по определению.
Итак, если ваше глобальное "состояние" не изменится, у вас все в порядке.
Также см. Ссылочную прозрачность:
Более тонкий пример - функция, которая использует глобальную переменную (или переменную с динамической областью действия, или лексическое замыкание), чтобы помочь ей вычислить свои результаты. Поскольку эта переменная не передается в качестве параметра, но может быть изменена, результаты последующих вызовов функции могут отличаться, даже если параметры идентичны. (В чисто функциональном программировании деструктивное присвоение недопустимо; таким образом, функция, которая использует глобальные (или динамически изменяемые) переменные, по-прежнему прозрачна по ссылкам, поскольку эти переменные не могут изменяться.)