Vvmebel.com

Новости с мира ПК
0 просмотров
Рейтинг статьи
1 звезда2 звезды3 звезды4 звезды5 звезд
Загрузка...

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

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

    Переводы, 23 января 2017 в 13:43

Если вы такой же разработчик, как и я, то наверняка сперва изучали парадигму ООП. Первым вашим яыком были Java или C++ — или, если вам повезло, Ruby, Python или C# — поэтому вы наверняка знаете, что такое классы, объекты, экземпляры и т.д. В чём вы точно не особо разбираетесь, так это в основах той странной парадигмы, называющейся функциональным программированием, которая существенно отличается не только от ООП, но и от процедурного, прототипно-ориентированного и других видов программирования.

Функциональное программирование становится популярным — и на то есть причины. Сама парадигма не нова: Haskell, пожалуй, является самым функциональным языком, а возник он в 90-ых. Такие языки, как Erlang, Scala, Clojure также попадают под определение функциональных. Одним из основных преимуществ функционального программирования является возможность написания программ, работающих конкурентно (если вы уже забыли, что это — освежите память прочтением статьи о конкурентности), причём без ошибок — то есть взаимные блокировки и потокобезопасность вас не побеспокоят.

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

Вступление: Все эти принципы не обязательны (многие языки следуют им не полностью). Все они теоретические и нужны для наиболее точного определения функциональной парадигмы.

1. Все функции — чистые

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

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

Первое правило понятно — если я вызываю функцию sum(2, 3) , то ожидаю, что результат всегда будет равен 5. Как только вы вызываете функцию rand() , или обращаетесь к переменной, не определённой в функции, чистота функции нарушается, а это в функциональном программировании недопустимо.

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

2. Все функции — первого класса и высшего порядка

Эта концепция — не особенность ФП (она используется в Javascript, PHP и других языках) — но его обязательное требование. На самом деле, на Википедии есть целая статья, посвящённая функциям первого класса. Для того, чтобы функция была первоклассной, у неё должна быть возможность быть объявленной в виде переменной. Это позволяет управлять функцией как обычным типом данных и в то же время исполнять её.

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

3. Переменные неизменяемы

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

4. Относительная прозрачность функций

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

Пусть у нас есть Java-функция, которая складывает 3 и 5:

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

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

5. Функциональное программирование основано на лямбда-исчислении

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

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

Как я уже говорил, лямбда-исчисление на этом не заканчивается — но мы рассмотрели лишь ключевые аспекты, связанные с ФП. Теперь, в разговоре о функциональном программировании вы сможете блеснуть словечком “лямбда-исчисление”, и все подумают, что вы шарите

Заключение

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

Если вы хотите узнать о функциональном программировании побольше, то советуем вам ознакомиться с примерами использования принципов ФП в JavaScript (часть 1, часть 2), а также с циклом статей, посвящённым функциональному C#.

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

Чем оно лучше/хуже императивного программирования в плане разработке ПО? Какие крупные комплексы ПО были написаны (созданы) с использование этой парадигмы начиная с ее зарождения?

Перемещено mono из talks

никакие. уже выяснили, что всё пишут/писали на С/С++/дельфи/шарп/джава, ради разнообразия используя питон в качестве вспомогательного инструмента. ну ещё есть 1-о (одно) приложение, написанное на ЛИСП. на ФП не написано ровным счётом ничего крупного.

Хацкель и Лисп не нужны.

А почему нужно ФП — курите

Какие крупные комплексы ПО были написаны (созданы) с использование этой парадигмы начиная с ее зарождения?

Кто скажет, что Emacs не крупный, пусть первый бросит в меня камень.

Главное преимущество — повод посоздовать тредов на лоре, да и то лиспосрачи уже не те.

sudo cast anonimous

Допустимая скорость разработки возможна только на языках с показателем от 10 до 20 матов в час.

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

Она существует как и императивное программирование. Уже почти 50 лет. Сколько еще ждать? =)

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

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

Читать еще:  Понятие объектно ориентированного программирования

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

Чем оно лучше/хуже императивного программирования в плане разработке ПО?

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

Оно не лучше/хуже оно другое.

Какие крупные комплексы ПО были написаны (созданы) с использование этой парадигмы начиная с ее зарождения?

ejabberd, emacs. Еще у относительно многих компаний внутренние сервисы бегают на функциональных языках, в этой среде достаточно популярен ML. Особенно в среде всяких валютных операций, прогнозов и так далее.

В любом случае интерес к нему растет, в особенности в международном сообществе, на том же hackernews почти каждый день несколько ФП релейтед ссылок висит.

Так это же пристанище аутсайдеров, типа ЛОРа.

Не станет ли она [система] лебединой песней этой парадигме? Ведь за период своего существования она должна была перейти из теоретико-академического сегмента (50-60 гг) в производственный сегмент(90-2000 гг), не? Мне хотелось бы разделить ваше мнение, но увы, как мне кажется, она останется лишь красивым теоретическим методом в будущем. Вспоминаю поговорку одного полковника «На%;й индукцию — давай продукцию». Хотя теория нужна =)

В Emacs императивщина во все поля.

Ведь за период своего существования она должна была перейти из теоретико-академического сегмента (50-60 гг) в производственный сегмент(90-2000 гг), не?

Не. Она уже в 1995 году перешла в производственный сегмент, когда C++ программисты из Ericsson зафейлили проект AXN-E (ATM свич), а через три года зарелизили AXD, использовав то же железо, но переписав софт на Erlang.

Лиспосрачи интересные. Иногда ищу через поиск тему потолще и читаю, загугливая неизвестные слова.

Сначала дай определение функциональному программированию.

Сначала дай определение функциональному программированию.

Это же нарицательное название типа мамкиного борща.

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

Шарп видел? Вот там фп применено как надо(LINQ). В чистом виде оно ненужно совершенно.

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

Шарп видел? Вот там фп применено как надо(LINQ). В чистом виде оно ненужно совершенно.

Я щитаю, что ФП-подход — это дрочево под компилятор, и ничего более, если кратко. Раздутый, распиаренный пшик. Если хомяк пишет фп, это выгодно хозяину этого хомяка, а вовсе не самому ему.

Покажи свой код.

ЩИТО?! Целая книга посвящена одним только сраным лямбдам? На кого это вообще рассчитано?

Я щитаю, что ФП-подход — это дрочево под компилятор,

Гораздо легче делается многопоточность, гораздо легче тестирование, проще прикручивать (де)сериализацию.

Компилятору как раз абсолютно пофиг. C++ компилируется в функциональный LLVM, а функциональный чистый Хаскелл в императивный ассемблер.

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

Компилятору как раз абсолютно пофиг

Я имею в виду оптимизацию

гораздо легче тестирование

Это из той же оперы.

Lisp — ФП? Что такого есть в лиспе из ФП? ФВП есть, еще что?

ФВП уже есть почти во всех мейнстрим языках. ФП ненужно?

Обязательно изучите функциональное программирование в 2017 году

Функциональное программирование существует уже очень давно, начиная с появления языка программирования Lisp в 50-х годах прошлого века. И, если вы заметили, на протяжении последних двух лет такие языки, как Clojure, Scala, Erlang, Haskell и Elixir, создают много шума и привлекают к себе внимание.

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

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

Как мы уже говорили, функциональное программирование берет свое начало еще в 50-х годах с момента создания Lisp для работы в серии научных компьютеров IBM700/7000. Lisp представил множество парадигм и особенностей, которые теперь мы связываем с функциональным программированием, и хотя мы можем назвать Lisp дедушкой функционального программирования мы можем копнуть глубже и взглянуть на еще большую общность между всеми функциональными языками программирования — лямбда-исчисление.

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

Лямбда-исчисление обладает свойством полноты по Тьюрингу, то есть является универсальной моделью вычислений, которая может быть использована для моделирования любой одноленточной машины Тьюринга. Ее тезка, греческая буква лямбда (λ), используется в лямбда-выражениях и лямбда-условиях для обозначения связывания переменной с функцией. — Википедия

Лямбда-исчисление — удивительно простая, но мощная концепция. В основе лямбда-исчисления лежат два понятия:

  • Функциональная абстракция, использующаяся для обобщения выражений посредством введения имен (переменных)
  • Функциональное применение, которое используется для вычисления обобщенных выражений путем присвоения переданных имен к определенным значениям

В качестве примера давайте рассмотрим функцию f с одним аргументом, увеличивающую аргумент на единицу:

Допустим, мы хотим применить функцию к числу 5 . Тогда функцию можно читать следующим образом:

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

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

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

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

Затем мы легко можем вызвать эту функцию:

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

Функции высшего порядка — функции, принимающие одну или несколько функций в качестве аргументов и/или возвращающие новую функцию. Для демонстрации концепции давайте снова воспользуемся нашей функцией double :

В этом примере Enum.map в качестве первого аргумента принимает перечисляемый — список, а в качестве второго — функцию, которую мы только что определили. Затем Enum.map применяет функцию к каждому элементу списка. В результате мы получаем:

Неизменяемое состояние

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

Как и прежде, давайте воспользуемся Elixir для иллюстрации:

В примере выше наша переменная tuple никогда не изменит своего значения. В третьей строке put_elem возвращает совершенно новый tuple без изменения значения оригинала.

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

  • Функциональное программирование существует уже давно (с начала 50-х годов)
  • Функциональное программирование основано на математических концепциях, в частности на лямбда-исчислениях
  • Функциональное программирование считалось слишком медленным по сравнению с императивными языками
  • Функциональное программирование возвращается
Читать еще:  Модуль безопасности tpm

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

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

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

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

Но не надо верить мне на слово, вы можете найти достаточно доказательств, посмотрев на технологические новости стартапов, таких как WhatsApp и Discord:

  • 900 миллионов пользователей WhatsApp поддерживают всего лишь 50 инженеров, используя Erlang
  • Discord подобным образом обрабатывают более миллиона запросов в минуту с использованием Elixir

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

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

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

В первом случае основные принципы понятны: вы оперируете математической логикой для вывода новых фактов и состояний из уже известных. Ярким примером такого языка является Prolog.

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

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

Что это

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

Функциональное программирование, несмотря на кажущуюся сложность, несёт в себе ряд преимуществ:

  1. Код становится короче;
  2. Понятнее;
  3. Включает в себя признаки хороших императивных языков: модульность, типизация, чистота кода.

Примерами функциональных языков являются LISP (Clojure), Haskell, Scala, R. В общем-то, вы даже можете попробовать писать функциональный код на Python или Ruby, но это больше развлечение для мозгов, нежели рациональное использование возможностей языка.

Конкретнее

Логично, что по функциональному программированию, существующему уже почти 50 лет, написано множество книг и статей. Поэтому какой смысл представлять собственную версию «ФП для чайников», если всё уже в прекрасном и удобочитаемом виде давно есть в сети? Поэтому просто поделимся ссылками:

  1. Прекрасная статья, имеющая исторический экскурс, яркие образы, но главное хорошие примеры. Имеется перевод.
  2. Книга, которую необходимо прочитать каждому функциональщику, если можно так выразиться. Тоже есть на русском.
  3. Онлайн-курс, который можно прослушать на английском языке. Будем надеяться, что-то похожее скоро появится и у нас на GeekBrains.
  4. Забавное и познавательное слад-шоу на тему функционального программирования.
  5. Прекрасная книга про Haskell, написанная доступным языком (русским), для тех, кто созрел для полноценного изучения первого функционального языка. Справочник прилагается.
  6. Для тех, кто предпочитает начать изучение не с простого, а с хронологического начала – перевод книги Кристиана Кеннека «Les Langages Lisp». Она же «Lisp in Small Pieces».

Куда с этими знаниями идти

Что касается области применения, то функциональное программирование является незаменимым инструментом при создании искусственного интеллекта или в тех областях, где императивные языки потребляют слишком много ресурсов (например, в Data Science). Так что если решили направить свою дальнейшую карьеру в это русло, то самое время обложиться описанной выше литературой и оставить свой след в чьей-то виртуальной голове.

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

В первом случае основные принципы понятны: вы оперируете математической логикой для вывода новых фактов и состояний из уже известных. Ярким примером такого языка является Prolog.

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

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

Что это

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

Функциональное программирование, несмотря на кажущуюся сложность, несёт в себе ряд преимуществ:

  1. Код становится короче;
  2. Понятнее;
  3. Включает в себя признаки хороших императивных языков: модульность, типизация, чистота кода.

Примерами функциональных языков являются LISP (Clojure), Haskell, Scala, R. В общем-то, вы даже можете попробовать писать функциональный код на Python или Ruby, но это больше развлечение для мозгов, нежели рациональное использование возможностей языка.

Конкретнее

Логично, что по функциональному программированию, существующему уже почти 50 лет, написано множество книг и статей. Поэтому какой смысл представлять собственную версию «ФП для чайников», если всё уже в прекрасном и удобочитаемом виде давно есть в сети? Поэтому просто поделимся ссылками:

  1. Прекрасная статья, имеющая исторический экскурс, яркие образы, но главное хорошие примеры. Имеется перевод.
  2. Книга, которую необходимо прочитать каждому функциональщику, если можно так выразиться. Тоже есть на русском.
  3. Онлайн-курс, который можно прослушать на английском языке. Будем надеяться, что-то похожее скоро появится и у нас на GeekBrains.
  4. Забавное и познавательное слад-шоу на тему функционального программирования.
  5. Прекрасная книга про Haskell, написанная доступным языком (русским), для тех, кто созрел для полноценного изучения первого функционального языка. Справочник прилагается.
  6. Для тех, кто предпочитает начать изучение не с простого, а с хронологического начала – перевод книги Кристиана Кеннека «Les Langages Lisp». Она же «Lisp in Small Pieces».

Куда с этими знаниями идти

Что касается области применения, то функциональное программирование является незаменимым инструментом при создании искусственного интеллекта или в тех областях, где императивные языки потребляют слишком много ресурсов (например, в Data Science). Так что если решили направить свою дальнейшую карьеру в это русло, то самое время обложиться описанной выше литературой и оставить свой след в чьей-то виртуальной голове.

Читать еще:  С язык программирования учебник

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

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

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

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

На практике отличие математической функции от понятия «функции» в императивном программировании заключается в том, что императивные функции могут опираться не только на аргументы, но и на состояние внешних по отношению к функции переменных, а также иметь побочные эффектыи менять состояние внешних переменных. Таким образом, в императивном программировании при вызове одной и той же функции с одинаковыми параметрами, но на разных этапах выполнения алгоритма, можно получить разные данные на выходе из-за влияния на функцию состояния переменных. А в функциональном языке при вызове функции с одними и теми же аргументами мы всегда получим одинаковый результат: выходные данные зависят только от входных. Это позволяет средам выполнения программ на функциональных языках кешировать результаты функций и вызывать их в порядке, не определяемом алгоритмом. (см.ниже Чистые функции)

λ-исчисления являются основой для функционального программирования, многие функциональные языки можно рассматривать как «надстройку» над ними[1].

[править]Повышение надёжности кода

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

[править]Удобство организации модульного тестирования

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

Таким образом, имеется возможность протестировать каждую функцию в программе, просто вычислив её от различных наборов значений аргументов. При этом можно не беспокоиться ни о вызове функций в правильном порядке, ни о правильном формировании внешнего состояния. Если любая функция в программе проходит модульные тесты, то можно быть уверенным в качестве всей программы. В императивных программах проверка возвращаемого значения функции недостаточна: функция может модифицировать внешнее состояние, которое тоже нужно проверять, чего не нужно делать в функциональных программах[12].

[править]Возможности оптимизации при компиляции

Традиционно упоминаемой положительной особенностью функционального программирования является то, что оно позволяет описывать программу в так называемом «декларативном» виде, когда жесткая последовательность выполнения многих операций, необходимых для вычисления результата, в явном виде не задаётся, а формируется автоматически в процессе вычисления функций.[источник не указан 1064 дня] Это обстоятельство, а также отсутствие состояний даёт возможность применять к функциональным программам достаточно сложные методы автоматической оптимизации.

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

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

Для преодоления недостатков функциональных программ уже первые языки функционального программирования включали не только чисто функциональные средства, но и механизмы императивного программирования (присваивание, цикл, «неявный PROGN» были уже в LISPе). Использование таких средств позволяет решить некоторые практические проблемы, но означает отход от идей (и преимуществ) функционального программирования и написание императивных программ на функциональных языках.[источник не указан 1064 дня] В чистых функциональных языках эти проблемы решаются другими средствами, например, в языке Haskell ввод-вывод реализован при помощи монад — нетривиальной концепции, позаимствованной из теории категорий.

Хвостовая рекурсия — специальный случай рекурсии, при котором рекурсивный вызов функцией самой себя является её последней операцией.[1] Подобный вид рекурсии примечателен тем, что может быть легко заменён на итерацию, что реализовано во многих оптимизирующих компиляторах. Когда происходит вызов функции, компьютер должен запомнить место, из которого функция была вызвана (адрес возврата), чтобы после её окончания вернуться и продолжить выполнение программы. Обычно адрес возврата сохраняется в стеке. Иногда последнее действие функции после завершения всех других операций, это просто вызов функции, возможно самой себя, и возвращение результата. В этом случае нет необходимости запоминать адрес возврата, вновь вызываемая функция будет возвращать результат непосредственно к месту вызова первоначальной функции. Хвостовая рекурсия часто применяется в программах на функциональных языках программирования. Многие вычисления на таких языках естественно выражать в виде рекурсивных функций, а возможность автоматической замены транслятором хвостовой рекурсии на итерацию означает, что по вычислительной эффективности она равна эквивалентному коду, записанному в итеративном виде.

Создатели функционального языка Scheme, одного из диалектов Lisp, оценили важность хвостовой рекурсии настолько, что в спецификации языка предписали каждому транслятору этого языка в обязательном порядке реализовывать оптимизацию хвостовой рекурсии.[2]

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

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

Ссылка на основную публикацию
Adblock
detector