Стиль программирования функциональный: Что такое функциональное программирование? / Хабр

Содержание

что это такое простыми словами, где применяется и что значит – SkillFactory

Функциональные языки программирования — это языки, в которых процессы представлены как функции в математическом понимании этого слова. То есть функция в них определяется не как подпрограмма, а как соответствие между множествами.

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

Функциональный подход — противоположность императивному, в котором программист задает программе четкий порядок действий по шагам. Тут все сложнее: программа сама решает, как и в каком порядке исполнять действия, а программист описывает правила взаимодействия и связи между компонентами.

Кто и где пользуется функциональным программированием

Сейчас программисты чаще всего работают с ООП — объектно-ориентированным программированием. Функциональный подход используют реже: он сложнее и применим не ко всем задачам. Но сейчас его популярность растет, и тому есть причины: чистота кода, надежность программ, высокие возможности для оптимизации.

Благодаря своим особенностям функциональное программирование распространено при работе с важными данными или при решении задач, где нужны сложные вычисления. Есть фреймворки, с которыми проще работать в функциональном стиле, а есть такие, в которых сочетаются оба подхода. Как пример — React и Redux для JavaScript.

Какие языки программирования функциональные

Условно можно выделить две группы. Первая — языки, жестко ориентированные на функциональное программирование. Вторая — так называемые мультипарадигменные языки, то есть такие, на которых можно писать по-разному. В том числе в функциональном стиле.

К функциональным языкам относятся Haskell, F#, OCaml, ELM, серия языков Lisp, а также Erlang и его потомок Elixir. Иногда сюда же относят Scala и Nemerle, хотя эти языки дают возможность программировать и в функциональном, и в императивном стилях. Они старые и сейчас применяются не так часто, как большинство современных.

Еще к этой группе относится несколько узкоспециализированных языков: язык вычислительной платформы Wolfram, языки J и K для финансового анализа, язык R для статистических целей. На функциональном языке APL базируется язык научной математической среды MATLAB. Также сюда можно отнести языки, которые используются при работе с электронными таблицами, а еще, частично, SQL — язык запросов для работы с базами данных.

К мультипарадигменным языкам, на которых можно писать в функциональном стиле, относятся уже упомянутые Scala и Nemerle, а также Go, JavaScript и некоторые его фреймворки. В меньшей степени сюда же можно отнести Python, Ruby, PHP и C++, а также Java: они больше ориентированы на ООП, но в них есть и функциональные элементы.

Разница между функциональным и императивным подходом

Чтобы лучше понять, как это работает, воспользуемся аналогией.

  • Императивная парадигма похожа на правила умножения в столбик. Последовательность действий, их порядок и тип четко определены. Мы выполняем команды, которые кто-то придумал до нас, как по инструкции.
  • Функциональная парадигма — это, скорее, правила орфографии и пунктуации. Нет четкой последовательности, как именно их применять. Правила нельзя представить как строгую инструкцию. Вместо этого мы сами решаем, какое правило в какой ситуации будет актуально. И последовательность, в которой мы это делаем, не имеет значения.

В чем разница с ООП

Объектно-ориентированное программирование отличается от функциональной парадигмы. В нем все представлено в виде объектов, в функциональном — в виде функций. ООП смешивает данные и поведение, функциональный подход — разделяет. Различаются особенности работы с информацией, структура программ и многое другое.

ООП в целом относится скорее к императивному типу программирования: код — это набор команд, рассказывающих компьютеру, что делать. Но «чистым» императивным программированием его назвать сложно — скорее, дополненным и измененным.

Сложность изучения функциональных языков

О функциональном программировании можно услышать, что оно сложно в освоении. Но тут есть парадокс, о котором говорят некоторые программисты: новичку понять его принципы может быть легче, чем разработчику с опытом программирования в ООП. Это связано с тем, что разработчики в императивных стилях уже привыкли к определенному типу логики, а перестроиться на что-то принципиально новое сложнее, чем изучать с нуля.

Сейчас считается, что хороший разработчик должен разбираться в обеих парадигмах и знать, когда лучше применять одну, а когда — другую.

Особенности функционального подхода

Функциональное программирование определяется несколькими важными правилами. Это основы, которые нужно знать, чтобы представлять, как в принципе работает парадигма.

Отсутствие жесткой последовательности. Об этом мы уже говорили. Разработчик задает правила, а компилятор кода сам решает, в какой последовательности их выполнять. Жесткий порядок действий программист не задает. Его выбирает сама программа.

«Чистые» функции. Чистые функции — это такие, которые удовлетворяют двум условиям:

  • при одинаковых входных данных функция всегда вернет одинаковый результат. То есть, функция, возвращающая сумму a и b, может быть чистой, а функция, возвращающая случайное число, — нет;
  • когда функция выполняется, не возникают побочные эффекты — так называют действия, которые влияют на что-то за ее пределами. Например, изменение переменной, чтение данных или вывод в консоль — это побочные эффекты.

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

Неизменные переменные. В функциональном программировании нет переменных в привычном виде. В нем все объявленные переменные неизменны — то есть фактически это константы. Если с какой-то переменной нужно провести вычисления, она не изменяется: создается новая переменная, и результат вычислений записывается в нее. А исходная остается прежней — ее значение не меняется.

«Первоклассные» функции высшего порядка. Все функции в функциональном программировании должны быть первого класса и высшего порядка. Сейчас объясним, что это значит.

  • Функция первого класса — это такая, которую можно представить как переменную. То есть, ее можно передавать как аргумент другим функциям, возвращать как результат работы других функций, сохранять в переменную или структуру данных.
  • Функция высшего порядка — такая, которая принимает в качестве аргументов функции или возвращает их в качестве результата.

Возможность работы с такими функциями есть не только в функциональном программировании. Более того, такое требование есть не только в нем. Но для него такой подход обязателен — вместе с другими особенностями. 

Относительная прозрачность. Еще одно требование к функциям в функциональном программировании — относительная прозрачность. Это понятие может быть сложным для понимания, но мы постараемся его объяснить. Относительная прозрачность означает, что выражение, которое возвращает функция, можно заменить значением — и от этого ничего не изменится. То есть, если функция, например, складывает два числа 3 и 5, то она вернет сумму 3 + 5. Теоретически вместо этой функции в выражение можно подставить число 8, и от этого программа не изменится — она будет работать так же.

Это не означает, что функция должна выдавать одинаковый результат во всех случаях — только при одинаковых входных данных. Про это также говорит часть определения чистой функции.

Рекурсия вместо циклов. В классическом функциональном программировании циклы реализованы как рекурсия. Стоит понимать разницу:

  • цикл — несколько выполнений одной и той же части кода подряд;
  • рекурсия — явление, когда функция вызывает сама себя, но с другими аргументами.

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

Лямбда-исчисление. Это особая математическая система, которая используется в функциональных языках программирования. Ее название также иногда пишут как λ-исчисление. Мы не будем углубляться в сложные математические понятия и выделим только несколько особенностей, важных для понимания функционального программирования:

  • в λ-исчислении есть две основных операции — аппликация и абстракция. Первое — это, по сути, вызов функции к заданному значению. Второе — построение функции по имеющимся выражениям;
  • все функции могут быть анонимными и складываться только из списка аргументов. Анонимные функции — это такие, у которых нет уникального имени, а объявляются они в месте выполнения;
  • при вызове функции с несколькими аргументами происходит ее каррирование — преобразование в несколько функций, в каждой из которых один аргумент. То есть, функция вида f(a, b, c) превратится в набор функций f(a)(b)(c). Результатом f(a) будет функция, которая тут же применится к аргументу b. И так далее. Это рекурсия — та, о которой мы говорили выше.

Преимущества функциональных языков

Чистота кода. Код, написанный на функциональном языке, выглядит чистым и понятным. Сюда же можно отнести локальную читаемость — можно разобраться, как работает та или иная функция, без строгой привязки к остальному коду. Код более чистый еще и за счет отсутствия четкой последовательности: чтобы понять происходящее в нем, не обязательно знать порядок выполнения разных действий.

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

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

Удобное тестирование. Благодаря все тем же чистым функциям этот стиль программирования удобнее отлаживать и тестировать. Особенно это заметно при модульном тестировании — таком, где каждый компонент проверяется по отдельности. Ведь если мы проверяем функцию, которая не изменяет ничего снаружи — значит, нам не нужно дополнительно думать о тестировании возможных побочных эффектов.

Распараллеливание вычислений. За счет отсутствия жесткой последовательности функциональное программирование отлично подходит для параллельных вычислений — одновременного выполнения нескольких действий. С императивным подходом их сложнее организовать, кроме того, нужно учитывать побочные эффекты. А функциональное программирование гарантирует, что вызов одной функции не повлияет на вызов другой — поэтому снижается риск ошибок и конфликтов при параллельных вычислениях.

Гибкая работа с функциями. Благодаря гибкой и сложной работе с функциями некоторые действия можно выполнять быстрее и удобнее, чем с императивным подходом. Это мощный инструмент, особенно для решения специфических задач: математических, научных, связанных с точными вычислениями или подобными сферами. Популярность подхода при решении таких задач видно и на практике: языки для математических, научных, экономических или статистических расчетов — по большей части функциональные.

Недостатки функциональных языков

Использование большого объема памяти. Этот минус вытекает из тех же особенностей, что и преимущества. Многие действия построены на рекурсии, а при изменении любого значения создается новая переменная — поэтому программа начинает требовать больше памяти, чем императивная с классическими циклами и изменяемыми значениями. Это значит, что для эффективной работы в языке должен быть мощный сборщик мусора или удобные инструменты для ручной работы с памятью. За ней нужно следить, иначе есть риск серьезного снижения производительности.

Непредсказуемый порядок действий. Эта особенность функционального программирования — плюс и минус одновременно. О плюсах мы уже говорили выше. Минус в том, что для некоторых важных задач порядок действий важен по определению. Например, ввод и вывод. Если данные будут вводиться или выводиться хаотично, в непредсказуемом порядке, это ухудшит работу программы. Поэтому часто функциональное программирование комбинируют с императивным — для большей гибкости и производительности кода в целом.

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

Как начать программировать в функциональном стиле

Сначала вам понадобится познакомиться с основами парадигмы и с теорией. Можно скомбинировать это с началом изучения функциональных языков, чтобы сразу «пощупать» подход на практике. Но помните, что многие решения сначала могут показаться вам неочевидными — к особым принципам нужно привыкнуть. Тем не менее, функциональное программирование – мощный и интересный инструмент, и изучить его вполне реально даже новичку.

Что такое функциональное программирование — Журнал «Код» программирование без снобизма

В программировании есть два больших подхода — императивное и функциональное. Они существенно отличаются логикой работы, ещё и создают путаницу в названиях. Сейчас объясним.

🤔 Функциональное — это про функции?

❌ Нет. Функциональное — это не про функции. Функции есть почти в любых языках программирования: и в функциональных, и в императивных. Отличие функционального программирования от императивного — в общем подходе.

Метафора: инструкция или книга правил

Представьте, что вы открываете кафе-столовую. Сейчас у вас там два типа сотрудников: повара и администраторы.

Для поваров вы пишете чёткие пошаговые инструкции для каждого блюда. Например:

  1. Налить воды в кастрюлю
  2. Поставить кастрюлю с водой на огонь
  3. Добавить в кастрюлю с водой столько-то соли
  4. Если нужно приготовить 10 порций, взять одну свёклу. Если нужно приготовить 20 порций, взять две свёклы.
  5. Почистить всю свёклу, которую вы взяли

Повар должен следовать этим инструкциям ровно в той последовательности, в которой вы их написали. Нельзя сначала почистить свёклу, а потом взять её. Нельзя посолить кастрюлю, в которой нет воды. Порядок действий важен и определяется вами. Это пример императивного программирования. Вы повелеваете исполнителем. Можно сказать, что исполнители выполняют ваши задания.

Для администратора вы пишете не инструкцию, а как бы книгу правил:

  • У нас нельзя со своим. Если гости пришли со своим, то сделать им замечание такое-то.
  • В зале должно быть чисто. Если в зале грязно, вызвать уборщика.
  • Если образовалась очередь, открыть дополнительную кассу.

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

❌ Программисты, не бомбите

Конечно же, это упрощено для понимания. Вы сами попробуйте это нормально объяснить (можно прямо в комментах).

Императивное программирование

Примеры языков: C, С++, Go, Pascal, Java, Python, Ruby

Императивное программирование устроено так:

В языке есть команды, которые этот язык может выполнять. Эти команды можно собрать в подпрограммы, чтобы автоматизировать некоторые однотипные вычисления. В каком порядке записаны команды внутри подпрограммы, в том же порядке они и будут выполняться.

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

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

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

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

Последовательность выполнения подпрограмм регулируется программистом. Он задаёт нужные условия, по которым движется программа. Вся логика полностью продумывается программистом — как он скажет, так и будет. Это значит, что разработчик может точно предсказать, в какой момент какой кусок кода выполнится — код получается предсказуемым, с понятной логикой работы.

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

👉 Суть императивного программирования в том, что программист описывает чёткие шаги, которые должны привести код к нужной цели.

Звучит логично, и большинство программистов привыкли именно к такому поведению кода. Но функциональное программирование работает совершенно иначе.

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

Примеры языков: Haskell, Lisp, Erlang, Clojure, F#

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

Например, в ООП нужно задать объекты и правила их взаимодействия между собой, но также можно и написать просто код, который не привязан к объектам. Он как бы стоит в стороне и влияет на работу программы в целом — отправляет одни объекты взаимодействовать с другими, обрабатывает какие-то результаты и так далее.

Функциональное программирование здесь идёт ещё дальше. В нём весь код — это правила работы с данными. Вы просто задаёте нужные правила, а код сам разбирается, как их применять.

Если мы сравним принципы функционального подхода с императивным, то единственное, что совпадёт, — и там, и там есть команды, которые язык может выполнять. Всё остальное — разное.

Команды можно собирать в подпрограммы, но их последовательность не имеет значения. Нет разницы, в каком порядке вы напишете подпрограммы — это же просто правила, а правила применяются тогда, когда нужно, а не когда про них сказали.

Переменных нет. Вернее, они есть, но не в том виде, к которому мы привыкли. В функциональном языке мы можем объявить переменную только один раз, и после этого значение переменной измениться не может. Это как константы — записали и всё, теперь можно только прочитать. Сами же промежуточные результаты хранятся в функциях — обратившись к нужной, вы всегда получите искомый результат.

Функции всегда возвращают одно и то же значение, если на вход поступают одни и те же данные. Если в прошлом примере мы отдавали в функцию сумму в 1000 ₽, а на выходе получали скидку в зависимости от дня недели, то в функциональном программировании если функция получит в качестве параметра 1000 ₽, то она всегда вернёт одну и ту же скидку независимо от других переменных.

Можно провести аналогию с математикой и синусами: синус 90 градусов всегда равен единице, в какой бы момент мы его ни посчитали или какие бы углы у нас ещё ни были в задаче. То же самое и здесь — всё предсказуемо и зависит только от входных параметров.

Последовательность выполнения подпрограмм определяет сам код и компилятор, а не программист. Каждая команда — это какое-то правило, поэтому нет разницы, когда мы запишем это правило, в начале или в конце кода. Главное, чтобы у нас это правило было, а компилятор сам разберётся, в какой момент его применять.

В русском языке всё работает точно так же: есть правила правописания и грамматики. Нам неважно, в каком порядке мы их изучили, главное — чтобы мы их вовремя применяли при написании текста или в устной речи. Например, мы можем сначала пройти правило «жи-ши», а потом правило про «не с глаголами», но применять мы их будем в том порядке, какой требуется в тексте.

👉 Получается, что смысл функционального программирования в том, чтобы описать не сами чёткие шаги к цели, а правила, по которым компилятор сам должен дойти до нужного результата.

Почему разработчики влюбляются в функциональное программирование | Ари Джури, доктор философии

Тенденция от Python к Haskell не исчезнет в ближайшее время

Функциональный код набирает обороты. Фото Брук Кейгл на Unsplash

Функциональное программирование существует уже 60 лет, но до сих пор оно всегда было нишевым явлением. Хотя такие революционеры, как Google, полагаются на свои ключевые концепции, современный программист почти ничего об этом не знает.

Это скоро изменится. Такие языки, как Java или Python, не только перенимают все больше и больше концепций функционального программирования. Новые языки, такие как Haskell, становятся полностью функциональными.

Проще говоря, функциональное программирование — это построение функций для неизменяемых переменных. Напротив, в объектно-ориентированном программировании используется относительно фиксированный набор функций, и вы в основном изменяете или добавляете новые переменные.

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

Функциональное программирование на подъеме

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

medium.com

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

Наивно сформулированная функция — это вещь, которая преобразует некоторый ввод в некоторый вывод. Вот только это не всегда так просто. Рассмотрим эту функцию в Python:

 def square(x): 
return x*x

Эта функция тупая и простая; он принимает одну переменную x , предположительно int , или, возможно, float или double , и выдает квадрат этого числа.

Теперь рассмотрим эту функцию:

 global_list = []def append_to_list(x): 
global_list.append(x)

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

Функция не работала бы, если бы global_list не был определен заранее, а ее вывод — тот же список, хотя и измененный. Несмотря на то, что global_list никогда не объявлялся как ввод, он меняется, когда мы используем функцию:

 append_to_list(1) 
append_to_list(2)
global_list

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

Нечестность в отношении функций

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

Подумайте о том, как вы будете тестировать append_to_list : вместо того, чтобы просто читать первую строку и тестировать функцию с любым x , вам нужно прочитать все определение, понять, что оно делает, определить global_list и протестируйте его таким образом. То, что просто в этом примере, может быстро стать утомительным, когда вы имеете дело с программами, состоящими из тысяч строк кода.

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

 newlist = []def append_to_list2(x, some_list): 
some_list.append(x)append_to_list2(1,newlist)
append_to_list2(2,newlist)
newlist

На самом деле мы мало что изменили . Выход по-прежнему [1,2] , а все остальное тоже осталось прежним.

Однако мы изменили одну вещь: код теперь свободен от побочных эффектов. И это отличная новость.

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

Поддержание чистоты ваших функций означает их удобство обслуживания. Фото Кристины @ wocintechchat.com на Unsplash

Функциональное программирование — это написание чистых функций

Функция с четко объявленными входами и выходами не имеет побочных эффектов. А функция без побочных эффектов — это чистая функция.

Очень простое определение функционального программирования таково: написание программы только на чистых функциях. Чистые функции никогда не изменяют переменные, а только создают новые на выходе. (Я немного схитрил в приведенном выше примере: он идет по пути функционального программирования, но все еще использует глобальный список. Вы можете найти примеры получше, но здесь речь шла об основном принципе.)

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

Существует простое правило обнаружения побочных эффектов: поскольку каждая функция должна иметь какие-то входные и выходные данные, объявления функций, которые идут без каких-либо входных или выходных данных, должны быть нечистыми. Это первые объявления, которые вы, возможно, захотите изменить, если будете внедрять функциональное программирование.

Карта и уменьшить

В функциональном программировании нет циклов. Рассмотрим эти циклы Python:

 целых чисел = [1,2,3,4,5,6] 
нечетных_целых = []
квадратных_нечетных = []
всего = 0 для i в целых числах:
, если i%2 == 1
нечетных_целых .append(i)для i в нечетных_целых:
в квадрате.append(i*i)для i в квадратных_нечетных:
итого += i

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

Вместо этого рассмотрим следующее:

 from functools import reduceintegers = [1,2,3,4,5,6] 
нечетные_целые = фильтр(лямбда n: n% 2 == 1, целые числа) n: n * n, нечетные_целые)
итого = уменьшить (лямбда-акк, n: акк + n, квадрат_нечетных)

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

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

Лямбда-функции

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

Лямбда-функции — это инструменты, с помощью которых можно сделать программу функциональной. Но вы можете использовать лямбда-выражения и в объектно-ориентированном программировании.

Статическая типизация

Приведенный выше пример не имеет статической типизации. При этом он функционален.

Несмотря на то, что статическая типизация добавляет дополнительный уровень безопасности вашему коду, необязательно делать его функциональным. Хотя это может быть приятным дополнением.

Функциональное программирование на одних языках проще, чем на других. Фото Кристины @ wocintechchat.com на Unsplash

Perl

Perl использует совершенно иной подход к побочным эффектам, чем большинство языков программирования. Он включает магический аргумент $_ , что делает побочные эффекты одной из его основных функций. У Perl есть свои достоинства, но я бы не стал пробовать на нем функциональное программирование.

Java

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

Это не значит, что Java плохая. Но он не предназначен для тех задач, которые лучше всего решаются с помощью функционального программирования, таких как управление базами данных или приложения для машинного обучения.

Scala

Это интересно: цель Scala — объединить объектно-ориентированное и функциональное программирование. Если вы находите это странным, вы не одиноки: в то время как функциональное программирование направлено на полное устранение побочных эффектов, объектно-ориентированное программирование пытается сохранить их внутри объектов.

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

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

расшифровка, казалось бы, сложной концепции

medium.com

Python

Python активно поддерживает функциональное программирование. Вы можете видеть это по тому факту, что каждая функция по умолчанию имеет хотя бы один вход, сам . Это очень похоже на дзен Python: явное лучше, чем неявное!

Clojure

По словам его создателя, Clojure примерно на 80% функционален. Все значения неизменяемы по умолчанию, точно так же, как они нужны вам в функциональном программировании. Однако вы можете обойти это, используя оболочки изменяемых значений вокруг этих неизменяемых значений. Когда вы открываете такую ​​обертку, вещь, которую вы получаете, снова неизменна.

Haskell

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

Это еще не начало эры больших данных. Фото Остина Дистела на Unsplash

По сравнению с объектно-ориентированным программированием функциональное программирование по-прежнему остается нишевым явлением. Однако если включение принципов функционального программирования в Python и другие языки имеет какое-либо значение, то функциональное программирование, похоже, набирает обороты.

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

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

Спасибо за внимание! Если вы хотите узнать, как реализовать больше элементов функционального программирования в коде Python, следите за обновлениями. Я расскажу об этом в своем следующем рассказе.

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

Автор: Мэтью Мартин

Часы

Обновлено

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

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

Функциональные языки делают акцент на выражениях и объявлениях, а не на выполнении операторов. Следовательно, в отличие от других процедур, которые зависят от локального или глобального состояния, вывод значения в FP зависит только от аргументов, переданных в функцию.

В этом уроке вы узнаете-

  • Что такое функциональное программирование?
  • Характеристики функционального программирования
  • История функционального программирования
  • Функциональные языки программирования
  • Основная терминология и концепции функционального программирования
  • Преимущества функционального программирования
  • Ограничения функционального программирования
  • Функциональное программирование против объектно-ориентированного программирования

Характеристики функционального программирования

  • Метод функционального программирования фокусируется на результатах, а не на процессе
  • Акцент делается на том, что нужно вычислить
  • Данные неизменны
  • Функциональное программирование Разложить задачу на «функции»
  • Он основан на концепции математических функций, которые используют условные выражения и рекурсию для выполнения вычислений
  • Он не поддерживает итерации, такие как операторы цикла и условные операторы, такие как If-Else

История функционального программирования

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

  • LISP был первым функциональным языком программирования. Маккарти разработал его в 1960 году
  • В конце 70-х годов исследователи из Эдинбургского университета определили ML (мета-язык)
  • В начале 80-х в язык Hope были добавлены алгебраические типы данных для рекурсии и рассуждений по уравнениям
  • В 2004 году Инновация функционального языка «Scala».

Языки функционального программирования

Целью любого языка FP является имитация математических функций. Однако основной процесс вычислений в функциональном программировании отличается.

Вот некоторые наиболее известные языки функционального программирования:

  • Haskell
  • СМЛ
  • Кложур
  • Скала
  • Эрланг
  • Чистота
  • F#
  • ML/OCaml Lisp/схема
  • XSLT
  • SQL
  • Математика

Базовая терминология и понятия функционального программирования

Неизменяемые данные

Неизменяемые данные означают, что вы должны легко создавать структуры данных вместо изменения уже существующих.

Ссылочная прозрачность

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

Модульность

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

Ремонтопригодность

Ремонтопригодность — это простой термин, который означает, что программирование FP легче поддерживать, поскольку вам не нужно беспокоиться о случайном изменении чего-либо за пределами данной функции.

Функция первого класса

«Функция первого класса» — это определение, относящееся к сущностям языка программирования, которые не имеют ограничений на их использование. Поэтому первоклассные функции могут появляться в любом месте программы.

Закрытие

Закрытие — это внутренняя функция, которая может обращаться к переменным родительской функции даже после выполнения родительской функции.

Функции высшего порядка

Функции высшего порядка либо принимают другие функции в качестве аргументов, либо возвращают их в качестве результатов.

Функции высшего порядка допускают частичное применение или каррирование. Этот метод применяет функцию к своим аргументам по одному, так как каждое приложение возвращает новую функцию, которая принимает следующий аргумент.

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

«Чистая функция» — это функция, входы которой объявлены как входы, и ни один из них не должен быть скрыт. Выходы также объявляются как выходы.

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

Пример:

 Функция Pure(a,b)
{
вернуть а+б;
} 

Нечистые функции

Нечистые функции прямо противоположны чистым. У них есть скрытые входы или выходы; это называется нечистым. Нечистые функции нельзя использовать или тестировать изолированно, поскольку они имеют зависимости.

Пример

 int z;
функция нечистая () {
г = г+10;
} 

Композиция функций

Композиция функций объединяет две или более функций для создания новой.

Общие состояния

Общие состояния — важная концепция в ООП-программировании. По сути, это добавление свойств к объектам. Например, если жесткий диск является объектом, в качестве свойств можно добавить емкость хранилища и размер диска.

Побочные эффекты

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

Преимущества функционального программирования

  • Позволяет избежать путаницы и ошибок в коде
  • Проще тестировать и выполнять модульное тестирование и отлаживать код FP.
  • Параллельная обработка и параллелизм
  • Развертывание горячего кода и отказоустойчивость
  • Предлагает лучшую модульность с более коротким кодом
  • Повышение производительности труда разработчика
  • Поддерживает вложенные функции
  • Функциональные конструкции, такие как ленивые карты и списки и т. д.
  • Позволяет эффективно использовать лямбда-исчисление

Ограничения функционального программирования

  • Парадигма функционального программирования непроста, поэтому ее трудно понять новичку
  • Трудно поддерживать, так как многие объекты развиваются во время кодирования
  • Требуется много насмешек и обширная настройка окружения
  • Повторное использование очень сложно и требует постоянного рефакторинга
  • Объекты могут неправильно отображать проблему

Функциональное программирование в сравнении с объектно-ориентированным программированием

Метод

Функциональное программирование ООП
FP использует неизменяемые данные. ООП использует изменяемые данные.
Следует модели на основе декларативного программирования. следует императивной модели программирования.
Основное внимание уделяется: «Что вы делаете. в программе». Основное внимание в нем уделяется тому, «как вы программируете».
Поддерживает параллельное программирование. Нет поддержки для параллельного программирования.
Его функции не имеют побочных эффектов. может иметь множество побочных эффектов.
Управление потоком выполняется с использованием вызовов функций и вызовов функций с рекурсией. Процесс управления потоком выполняется с использованием циклов и условных операторов.
Порядок выполнения операторов не очень важен. Порядок выполнения операторов важен.
Поддерживает как «Абстракцию над данными», так и «Абстракцию над поведением».

Imacros | Все права защищены © 2021