Deutsch
Germany.ruФорумы → Архив Досок→ Программирование

Функтиональное програмирование

701  
koder патриот18.03.21 09:58
koder
18.03.21 09:58 

Прочитал статью на хабре

https://habr.com/ru/company/jugru/blog/545482/


Кто нибудь на пальцах может сказать, что такое функтиональное программирование и в чем его преимущество перед ООP

#1 
gans_myuller завсегдатай18.03.21 20:02
NEW 18.03.21 20:02 
в ответ koder 18.03.21 09:58

На пальцах все просто. У тебя есть только чистые функции и вся программа цепь вызова этих самых функций.
Чистая функция - это когда значение функции зависит только от входящих параметров и ни от чего больше. Никаких внешних
или глобальных переменных. Вообще никаких переменных. Ничего этого нет.
Ну и основные преимущества: Правильность работы программы можно доказать. Сильно упрощается тестирование.
Т.к. функции чистые, то нам не важен порядок вычислений и можно лучше оптимизировать выполнение. Например, один раз
вычислив функцию про заданных параметрах можно закэшировать результат.

#2 
MrSanders коренной житель18.03.21 20:09
NEW 18.03.21 20:09 
в ответ koder 18.03.21 09:58
то нибудь на пальцах может сказать, что такое функтиональное программирование и в чем его преимущество перед ООP

Могу попробовать...

параметры -> функция -> новый результат.

Для работы функции нужны только её параметры.

Функция получает параметры и возвращает результат. Что происходит внутри функции не меняет ни параметры ни систему (и именно поэтому IO это всегда головная боль).

Типы! Если вы поклонник дак-тайпинга, ну, яваскрипист или (не дай бог) пыхыпыст - проходите мимо.


Что это даёт?

Параллелизация. Так как функция самодостаточна их можно запускать хоть 100500 параллельно. Они друг-другу мешать не будут.

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

В среднем меньше ошибок (нет побочных эффектов и типизация).

Машины могут кешировать результаты вызовов. Если мы передали функции два параметра "10" и "Вася" и получили 42 нам не надо её ещё раз вызывать с этими же параметрами. Мы знаем что она вернет 42.

Математики в восторге... Но тут я уже всё что можно забыл... Можно про хаскел почитать - если продраться через систему типов, монады, функторы, композицию функций и те пе, становится очень интересно.


В чём недостаток... Имхо, главный в том, что думать надо по-другому. ООП более "общечеловеческое", его понять легче. Головная боль как связать красоту функций и реальный мир. I/O страшное дело.

#3 
koder патриот18.03.21 21:13
koder
NEW 18.03.21 21:13 
в ответ MrSanders 18.03.21 20:09

гм. Ну если мне надо пару значений перемножить, я действительно напишу функцию. Статическую. В статическом классе. Но в основном чистых функций не бывает. Допустим заказ в ресторане. Он зависит не только от входных параметров, но и от условий окружения. Класс для принятия решения собирает информацию. Из базы данных, из других источников. Сбор может быть сложным. Многоходовым. И это все в одной функции? И что делать, если она нечистая?

#4 
gans_myuller завсегдатай19.03.21 13:09
NEW 19.03.21 13:09 
в ответ koder 18.03.21 21:13

Окружение - это тоже функции передающиеся в функцию заказа.
Как взаимодействовать с нечистым окружением - отдельный вопрос. Делают, например, чистое ядро и вызывают его функции из нечистого кода.
Для вызова функций с побочными эффектами придумали монады и т.д. и т.п.

#5 
koder патриот19.03.21 13:48
koder
NEW 19.03.21 13:48 
в ответ gans_myuller 19.03.21 13:09
Окружение - это тоже функции передающиеся в функцию заказа.

Ок, Функция передается в функцию как параметр. Это значит, что результат выполнения верхней функции зависит от передаваемой. Какое отличие от классов и завицимостей в ООП? Это же тоже зависимости?

#6 
gans_myuller завсегдатай19.03.21 14:42
NEW 19.03.21 14:42 
в ответ koder 19.03.21 13:48

Естественно у тебя есть зависимости (значение функции прекрасно зависит от своих аргументов) и даже состояние, на самом деле, никуда не делось.
Просто раньше все было в переменных , а теперь размазано по стеку. Это просто другой подход при котором твоя программа - это просто цепочка вычислений.
В идеале ни циклов, ни переменных ни ифов. Ничего. Красота же!

#7 
MrSanders коренной житель19.03.21 18:55
NEW 19.03.21 18:55 
в ответ koder 18.03.21 21:13
гм. Ну если мне надо пару значений перемножить, я действительно напишу функцию. Статическую. В статическом классе. Но в основном чистых функций не бывает. Допустим заказ в ресторане. Он зависит не только от входных параметров, но и от условий окружения. Класс для принятия решения собирает информацию. Из базы данных, из других источников. Сбор может быть сложным. Многоходовым. И это все в одной функции? И что делать, если она нечистая?

Не-а. Замучаешься сложную, многоходовую делать. Кучу небольших функций пишешь, а потом "нанизываешь" в вызов. Класс собирает информацию (что против DI), а функция получает в параметрах.

Например, посчитаем стоимость заказа на хаскеле, если есть список блюд и функция, возвращающая цену (в которой будем прятать доступ к бд), она у нас "impure". Надеюсь что ещё не всё забыл и код частично правильный :)

calculateOrderPrice :: (Order -> Int) -> [Order] -> Int
calculateOrderPrice priceProvider [] = 0
calculateOrderPrice priceProvider (order:orders) = priceProvider order + calculateOrderPrice priceProvider orders
#8