Побочный эффект оказывает влияние на что-либо в мире, кроме возврата значения, то есть мутирует что-то, что может быть каким-то образом видно вне функции.
Чистая функция не зависит и не влияет на любое изменяемое состояние вне области этого вызова функции, что означает, что выходные данные функции зависят только от констант и ее входных данных. Это означает, что если вы дважды вызываете функцию с одинаковыми аргументами, вы гарантированно получите один и тот же результат оба раза, независимо от того, как написана функция.
Если у вас есть функция, которая изменяет переданную переменную, эта модификация является побочным эффектом, потому что она является видимым выводом функции, отличной от возвращаемого значения. Функция void, которая не запрещена, должна иметь побочные эффекты, потому что у нее нет другого способа воздействовать на мир.
Функция может иметь закрытую переменную, видимую только той функции, которую она читает и изменяет, и ее вызов все равно будет иметь побочный эффект изменения поведения функции в будущем. Быть чистым означает иметь ровно один канал для вывода любого вида: возвращаемое значение.
Можно генерировать случайные числа чисто, но вы должны вручную обойти случайное начальное число. Большинство случайных функций сохраняют частное начальное значение, которое обновляется каждый раз при его вызове, так что вы каждый раз получаете разные случайные значения. Вот фрагмент кода Haskell, использующий System.Random :
randomColor :: StdGen -> (Color, Int, StdGen)
randomColor gen1 = (color, intensity, gen2)
where (color, gen2) = random gen1
(intensity, gen3) = randomR (1, 100) gen2
Каждая из случайных функций возвращает рандомизированное значение и новый генератор с новым начальным числом (на основе предыдущего). Чтобы получить новое значение каждый раз, необходимо передать цепочку новых генераторов (gen1, gen2, gen3). Неявные генераторы просто используют внутреннюю переменную для хранения значений gen1 .. в фоновом режиме.
Делать это вручную - боль, и в Haskell вы можете использовать монаду состояний, чтобы сделать ее намного проще. Вы захотите реализовать что-то менее чистое или использовать средство, такое как монады, стрелки или значения уникальности, чтобы абстрагировать его.
Получение системного времени нечисто, потому что время может отличаться каждый раз, когда вы спрашиваете.
Сон размыт, потому что сон не влияет на результат функции, и вы всегда можете отложить выполнение с занятым циклом, и это не повлияет на чистоту. Дело в том, что сон делается ради чего-то другого, что является побочным эффектом.
Распределение памяти на чистых языках должно происходить неявно, потому что явное выделение и освобождение памяти являются побочными эффектами, если вы можете выполнять любые виды сравнения указателей. В противном случае создание двух новых объектов с одинаковыми параметрами будет по-прежнему иметь разные значения, поскольку они будут иметь разные идентификаторы (например, не будут равны оператору Java ==).
Я знаю, что немного поболтал, но, надеюсь, это объясняет, что такое побочные эффекты.