Функционалното програмиране (наричано също FP) е начин на мислене за изграждането на софтуер чрез създаване на чисти функции. Той избягва концепциите за споделено състояние, променливи данни, наблюдавани в обектно-ориентираното програмиране.

Функционалният стил има теоретични и практически предимства:

  • Формална доказуемост.
  • Модулност.
  • Съставимост.
  • Лесно отстраняване на грешки и тестване.

Официална доказуемост.

Теоретична полза е, че е по-лесно да се конструира математическо доказателство, че функционалната програма е правилна.

Техниката, използвана за доказване на правилността на програмите, е да се запишат инварианти, свойства на входните данни и на променливите на програмата, които винаги са верни. какво е инвариант? Ще обясня с пример от реалния живот.

инвариантът е нещо като фиксирана връзка между различни обекти. Например възрастта ви винаги ще бъде по-ниска от тази на вашите биологични родители. Както вашата възраст, така и възрастта на вашия родител се променят с течение на времето, но връзката, която споменах по-горе, е неизменна.

Инвариантът може да бъде и числена константа. Например стойността на pi е инвариантно съотношение между обиколката на кръга и неговия диаметър. Без значение колко голям или малък е кръгът, това съотношение винаги ще бъде pi.

Модулност

По-практическа полза от функционалното програмиране е, че то ви принуждава да разделите проблема си на малки части. В резултат на това програмите са по-модулни. По-лесно е да посочите и напишете малка функция, която прави едно нещо, отколкото голяма функция, която извършва сложна трансформация. Малките функции също са по-лесни за четене и проверка за грешки.

Композитивност

ще напишете редица функции с различни входове и изходи. Някои от тези функции неизбежно ще бъдат специализирани за конкретно приложение, но други ще бъдат полезни в голямо разнообразие от програми. Например функция, която взема път към директория и връща всички XML файлове в директорията, или функция, която взема име на файл и връща съдържанието му, може да се приложи в много различни ситуации.

С течение на времето ще създадете лична библиотека от помощни програми. Често ще сглобите нови програми, като подредите съществуващи функции в нова конфигурация и напишете няколко функции, специализирани за текущата задача. някаква полза от възможността за съставяне

  • По-малко повтаряща се работа по внедряване (DRY): Вместо да има безброй различни реализации на страниране, има само една, която се използва навсякъде.
  • Повече функционалност за дадено количество усилия за внедряване: Съществуващите примитиви могат да се комбинират за решаване на много по-голям набор от задачи, отколкото би бил случаят, ако същите усилия се насочат към внедряване на монолитни, несъставими команди.

Лекота на отстраняване на грешки и тестване.

Отстраняването на грешки е опростено, тъй като функциите обикновено са малки и ясно определени. Когато една програма не работи, всяка функция е интерфейсна точка, където можете да проверите дали данните са правилни. Можете да разгледате междинните входове и изходи, за да изолирате бързо функцията, която е отговорна за грешка.

Тестването е по-лесно, защото всяка функция е потенциален обект за единичен тест. Функциите не зависят от състоянието на системата, което трябва да бъде репликирано преди стартиране на тест; вместо това трябва само да синтезирате правилния вход и след това да проверите дали изходът отговаря на очакванията.

Чиста функция.

Чистите функции са функции, при които входът не трябва да бъде скрит или извън функцията.
Чистите функции действат върху техните параметри. функциите да бъдат чисти, тогава не променяйте стойността на входа или каквито и да е данни, които съществуват извън обхвата на функцията.

пример не е чиста функция.

пример за чиста функция

Неизменност

Неизменен обект е обект, който не може да се променя и състоянието му не може да се променя, след като е създаден.

Пример по-долу

в списъка на Python обектите са променливи

Кортежите са неизменни и не можете да променяте състоянието им

Итератори

итератор е обект, представляващ поток от данни; този обект връща данните един по един елемент наведнъж. Итераторът на Python трябва да поддържа метод, наречен __next__(), който не приема аргументи и винаги връща следващия елемент от потока. Ако няма повече елементи в потока, __next__() трябва да предизвика изключението StopIteration. Итераторите обаче не трябва да са крайни; напълно разумно е да напишете итератор, който произвежда безкраен поток от данни.

Вградената функция iter() взема произволен обект и се опитва да върне итератор, който ще върне съдържанието или елементите на обекта, повдигайки TypeError, ако обектът не поддържа итерация. Няколко от вградените типове данни на Python поддържат итерация, като най-често срещаните са списъци и речници. Един обект се нарича iterable, ако можете да получите итератор за него.

Генераторни изрази и разбиране на списъци

Две често срещани операции върху изхода на итератора са:

1) извършване на някаква операция за всеки елемент.

2) избор на подмножество от елементи, които отговарят на някакво условие.

Списъчните разбирания и генераторните изрази (кратка форма: „listcomps“ и „genexps“) са кратка нотация за такива операции, заимствана от езика за функционално програмиране Haskell (https://www.haskell.org/).

list_compression syntax [ expression for in value inplace if statement]
generator_expression syntax (expression for in value inplace if statement)

получавате обратно списък на Python; list_compresion е списък, съдържащ получените редове, а не итератор. Изразите на генератора връщат итератор, който изчислява стойностите според нуждите, без да е необходимо да материализира всички стойности наведнъж. Това означава, че разбирането на списъци не е полезно, ако работите с итератори, които връщат безкраен поток или много голямо количество данни. Генериращите изрази са за предпочитане в тези ситуации.

Ламбда изрази

Ламбда изразът е анонимна функция. Когато създаваме функции в Python, използваме ключовата дума def и ѝ даваме име. Ламбда изразите ни позволяват да дефинираме функция много по-бързо