Каковы побочные эффекты в предикатах и ​​почему они плохие?

Мне интересно, что считается побочным эффектом в предикатах для fnкак remove или же filter, Там, кажется, есть ряд возможностей. Понятно, что если предикат пишет в файл, это побочный эффект. Но рассмотрим ситуацию, подобную этой:

(def *big-var-that-might-be-garbage-collected* ...)

(let [my-ref *big-var-that-might-be-garbage-collected*]
  (defn my-pred
    [x]
    (some-operation-on my-ref x)))

Даже если some-operation-on это просто запрос, который не меняет состояние, тот факт, что my-pred сохраняет ссылку на *big... изменяет состояние системы так, что большая переменная не может быть собрана сборщиком мусора. Это также считается побочным эффектом?

В моем случае я хотел бы написать в систему ведения журнала в предикате. Это побочный эффект?

И почему именно побочные эффекты в предикатах не поощряются? Это потому что filter а также remove и их друзья работают лениво, так что вы не можете определить, когда вызываются предикаты (и, следовательно, когда происходят побочные эффекты)?

3 ответа

Решение

GC обычно не учитывается при оценке, является ли функция чистой или нет, хотя многие действия, которые делают функцию нечистой, могут иметь эффект GC.

Ведение журнала является побочным эффектом, как и изменение любого состояния в программе или мире. Чистая функция берет данные и возвращает данные, ничего не изменяя.

https://softwareengineering.stackexchange.com/questions/15269/why-are-side-effects-considered-evil-in-functional-programming описывает, почему побочных эффектов избегают в функциональных языках.

Например,

(first (filter odd? (range 20)))
; 1

Но если мы устроим odd? вывести его аргумент по ходу дела:

(first (filter #(do (print %) (odd? %)) (range 20)))

Будет печатать 012345678910111213141516171819 перед возвращением 1!

Причина в том, что filterгде это возможно, имеет дело со своим аргументом последовательности в кусках 32 элементов.

Если мы возьмем предел от range:

(first (filter #(do (print %) (odd? %)) (range)))

... мы получаем полноразмерный чанк: 012345678910111213141516171819012345678910111213141516171819202122232425262728293031

Просто печать аргумента сбивает с толку. Если побочные эффекты значительны, все может пойти не так, как надо.

Я нашел эту ссылку полезной

Проблема состоит в том, чтобы определить, когда или даже возникнут ли побочные эффекты при любом вызове функции.

Если вам важно, чтобы одни и те же входные данные возвращали один и тот же ответ, у вас все в порядке. Побочные эффекты зависят от того, как выполняется функция.

Другие вопросы по тегам