Страницы

Поиск по вопросам

среда, 27 ноября 2019 г.

Что такое функциональное программирование?

#функции #функциональное_программирование


Часто противопоставляют функциональный подход и ООП. Не совсем понятно, почему? Что
отличает функционально программирование? Лямбды и наличие функций типа map, fold, reduce
и т.д.?

Update:
В чем заключается функциональный подход с точки зрения практики?
    


Ответы

Ответ 1



Функциональное программирование - способ организации вычислений без состояния. Строго говоря, состояние у такой программы конечно есть, это - совокупность контекстов всех её функций. Но: главная проблема, стоящая за сложностями состояния, идентичности и изменения, состоит в том, что, введя присваивание, мы вынуждены внести в свои вычислительные модели понятие времени (time). До того, как появилось присваивание, наши программы от времени не зависели — в том смысле, что всякое выражение, обладающее значением, всегда имело одно и то же значение. На практике, используя ФП вы идёте от простого к сложному: организуете зависимости, отношения, преобразования и композиции функций. Способы делать это - суть методологии ФП. Функции ваши восновном "чисты", не мутируют внешнего контекста, а их результат зависит только от переданных параметров. ФП полностью избавляет от возможности совершения целого класса ошибок (cм. SICP Х. Абельсон, Д. Д. Сассман: гл. "Ловушки императивного программирования"). Неверно считать, что в функциональном стиле можно писать только на языке сверхвысокого уровня с искусственным интеллектом вместо компилятора. Разумеется, это можно делать на любом языке программирования, в котором есть функции высшего порядка. Более того, механика функций - основа любого интерпретатора и эта механика довольно проста, а вот введение самого понятия переменных и их мутации сильно усложняет устройство интерпретатора. ФП противопоставляют ООП восновном потому, что в обратную сторону пошла волна хайпа, созданная в своё время вокруг Java и C++. Оказалось, что библиотеки шаблонов и многоуровневые иерархии объектов не решили всех проблем, даже наоборот, создав новые. По-прежнему бесконтрольно возрастает сложность программных систем, а соответственно и их стоимость. Тут мы наблюдаем рациональное обращение отрасли к фундаментальным основам, имеющее целью уменьшить энтропию.

Ответ 2



В императивном подходе (а ООП может быть им, и обычно им и является), программист расписывает, как именно нужно исполнять его программу. В функциональном подходе программист пишет "что нужно сделать", а вот как это делать, решает компилятор или транслятор. Всякие лямбды, map/reduce ещё не делают программирование функциональным. Тут на самом деле комплексный подход. К примеру, в императивном стиле принято делать изменяемые переменные (да, тавтология), а в функциональном стиле принято использовать неизменяемые переменные и чистые функции (чистые функции это такие функции, результат которых зависит только от входных параметров и не зависит от ничего другого. Также они никак не изменяют окружение. А так как их результат не зависит от внешних параметров, то их результат можно закешировать или беспроблемно вычислять в параллель). В императивном подходе нужно детально расписать каждый шаг и в правильной последовательности. В функциональном просто - вычисли все это, вот тебе функция. И рантайм сам сообразит, как именно это вычислить, возможно переставив некоторые расчеты местами. Также в функциональном подходе активно используется "ленивый подход", когда некоторые функции могут не вычисляться до тех пор, пока они реально не понадобятся. И если, к примеру, рантайм видит, что нужно вычислить выражение сложная_функция(1,2)/сложная_функция(1,2), то он просто пишет 1 и даже не вычисляет - потому что нет смысла. В императивном подходе компилятор теоретически может сделать такую оптимизацию, но для этого ему нужно проанализировать функцию и убедиться, что она не имеет побочных эффектов и тому подобное.

Ответ 3



В противопоставлении ООП и функционального, проблему сужают до противопоставления того кем манипулирует, либо функциями, либо изменяемыми объектами. Но это слишком узкий взгляд: объектами могут быть функции и функции могут хранить значения. Императивное программирование стало популярно из-за относительно простой трансляции таких программ на популярные процессорные архитектуры, на которых программы, в функциональном стиле, особо выдающихся результатов не демонстрируют, т.е. более сложная и более продолжительная трансляция функциональных программ дает код несколько худшего качества на них. Но программы на изменяемых состояниях(объектах) невозможно смасштабировать, если заранее не внести дополнительные механизмы распределения нагрузки ( по ядрам, компьютерам, сетям ), разделения ресурсов ( файлов, общих зон памяти ) и взаимной коммуникации для получения результатов работы. Вопрос в другом — может ли функциональное программирование упростить решения этого вороха проблем?! И да, и нет. Высокоуровневое функциональное SQL представление помогает распределять нагрузку на реляционные базы, но об линейном росте от количества ядер(компьютеров) речь не идет. Высокий уровень OpenGL позволяет писать программы выполняющие гигантские объемы вычислений, даже в императивных языках(так он был создан), распределяя нагрузку на GPU ядрах. Но нехватка ресурсов была и остается узким местом любой программы, для любой операционной системы. А коммуникации — к решению этих проблем только подходят, и императивные языки пытаются решать их в функциональном стиле, полностью отказавшись от управления в «ручном» стиле «состояний».

Комментариев нет:

Отправить комментарий