В частности, в императивных языках (C, Pascal, C++, ...) side-effects - это единственный способ сделать что-то полезное.
Но вот если мы хотим параллелить что-то, анализировать и т.д., то side effects нам ооочень мешают.
Для того, чтобы понять, что есть side-effects сравним функцию в математическом и, скажем, в C-стиле.
Математическая функция будучи применена к заданному значению в области определения этой функции всегда возвращает одно и тоже значение, чтобы не случилось.
В качестве примера сишной функции возьмем fgetc. Значение этой функции существенно зависит от состояния внешнего мира, причем, она это состояние меняет. Это и есть сайд эффект
Во-первых, рассмотрим задачу некого поиска с откатом (например, пр решении задач теории игр). Такой поиск можно формализовать как поиск на дереве. Причем, мы имеем возможность откатываться на уровень выше, если в дальнейший поиск в данном поддереве не имеет смысла. В этом случае нам жизненно необходимо, чтобы состояние нашей "машины поиска" было явным, т.е. никакая функция не вызывала посторонних эффектов. В этом случае, для отката нам будет достаточно "вспомнить" это состояние.
Второй пример - распараллеливание и агрессивные оптимизации. Рассмотрим выражение $F_1(F_2(X), F_3(X))$. Если функции F_2 и F_3 не имеют сторонних эффектов, тогда мы можем вычислять их в любом порядке, и, более того, переносить их вычисления на другие узлы кластера, забирая лишь результаты вычисления.
Отсутствием сторонних эффектов характеризуются т.н. чистые функциональные языки, а так же логические языки. В частности, один из самых эффективных языков для параллельного научного программирования SISAL относится именно к группе чистых функциональных языков программирование. Для чистых языков характерны более простые и мощные оптимизаторы при генерации кода, возможность более просто формально доказывать правильность кода и т.д.
Спасибо. Но если чистые функциональные языки не имеют side-effect'a, то на них принципиально нельзя сделать скажем генеретор случайных чисел? Или, например, если требуется вычислить функцию от множества точек, которые не влазят в память за раз, скажем среднее или дисперсию или ковариацию или много чего еще о чем написано в учебнике по статистике, при условии что у меня есть памяти в 10 раз меньше чем данных. Как-то это решено скажем в OCamle'e, SISAL?
Да, во-первых, можно материализовать состояние внешнего мира и протаскивать его с помощью монад, как указал предыдущий собеседник.
Во-вторых, ваши задачи вполне решаеются без сайд эффектов. И способов решения много. В частности, можно использовать аккумуляторы - параметры, накапливающие значения. Т.к. итерация в ФЯ как правило реализуется через рекурсию, то аккумуляторы вполне решают свою задачу.
Харизматический пример :)))
let func x =
let rec _func x acc =
if x = 0 then
acc
else
_func (x-1) (acc*x)
in
_func x 1;;
Последовательность вызовов рекурсивной функции _func при
func 3:
_func 3 1
_func 2 3
_func 1 6
Т.е. наш любимый факториал.
При этом функция _func обладает свойством хвостовой рекурсии и
ри компилляции преобразуется в обыкновенный цикл.
ARia
А вы используете функциональные яызки в реальной работе? Если не секрет, то для чего. Что они дают по сравнению с С(++|#)/Python/Perl/Java и пр.
Пролистывая сайты/конфы где сидят пользователи ML возникает чувство, что там собрались фэны и говорят о вселенском счастье, которое наступит моментально после того как начнется использование ML везде. По крайней мере это спорно, но я пытаюсь понять почему они так в этом уверены.
Сам я пользуюсь С++, в основном потому, что часто нет решения (библиотек) на других языках. Например мне нужно что то типа SGI OpenInventor(Coin3D, SoFree). Эти библиотеки сильно "плюсоватые", а посему видимо трудно прицепить их к Python'у Ruby или OCaml'y. Есть VTK, но он кажется последние 3 года не выходит из состояния еще чуть-чуть и релиз.
Мне лично С++ не очень нравится за уменее дарить сюрпризы, особенно когда их совсем не надо, а хочется, что бы оно просто работало. Я конечно понимаю, что серебрянной пули нет, а вдруг ML (если верить господам из ML конф) хотя бы чуток посеребренная?
Ну, ML - это, конечно, не идеал :))) Но очень близко :)))
На OCaml я пишу всякого рода компилляторы, оптимизаторы and so on. В основном для разного рода DSL (domain-specific languages). Кроме этого, был опыт написания на нем некого гидродинамического кода. OCaml показал себя очень неплохо.
В общем, его знать достаточно полезно. По-крайней мере для обработки потоковых и древовидных структур (например, XML, AST и т.д.) лучше не найдешь. Кроме того, у него достаточно развитые средства синтаксического анализа, парсинга XML и т.д.