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

Обновлено: 30.06.2024

  • Для учеников 1-11 классов и дошкольников
  • Бесплатные сертификаты учителям и участникам

МИНИСТЕРСТВО ОБРАЗОВАНИЯ И НАУКИ РФ

ФЕДЕРАЛЬНОЕ ГОСУДАРСТВЕННОЕ БЮДЖЕТНОЕ ОБРАЗОВАТЕЛЬНОЕ УЧРЕЖДЕНИЕ ВЫСШЕГО ПРОФЕССИОНАЛЬНОГО ОБРАЗОВАНИЯ «МОРДОВСКИЙ ГОСУДАРСТВЕННЫЙ ПЕДАГОГИЧЕСКИЙ ИНСТИТУТ

Кафедра информатики и вычислительной техники

студентка 5 курса группы МДМ-213

кандидат физико-математических наук, доцент

Кормилицына Т. В.

Язык программирования - формальная знаковая система, предназначенная для записи компьютерных программ. Язык программирования определяет наборлексических, синтаксических и семантических правил, определяющих внешний вид программы и действия, которые выполнит исполнитель (обычно - ЭВМ) под её управлением.

Языки программирования классифицируются следующим образом:

1. императивные - программа представляет собой явное описание последовательности манипуляций над данными в памяти компьютера;

2. декларативные - программа содержит описание цели и средств её достижения. Они в свою очередь делятся на:

* функциональные - программа содержит описание функций, вызывающих друг друга;

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

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

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

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

3. Основными методами программирования являются суперпозиция функций и рекурсия.

4. Функциональное программирование есть программирование, управляемое данными. В строго функциональном языке однажды созданные (введенные) данные не могут быть изменены .

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

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

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

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

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

2. Отсутствует оператор присваивания.

3. Переменная обозначает только имя структуры.

4. В языке присутствуют функционалы.

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

1. Повышение надёжности кода.

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

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

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

3. Возможности оптимизации при компиляции.

4. Возможности параллелизма.

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

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

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

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

* краткость и простота;

* функции - это значения;

* чистота (отсутствие побочных эффектов);

* отложенные (ленивые) вычисления.

Краткость и простота

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

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

Пример 1: Метод сортировки Хоара на С.

static void qs( int [] items, int left, int right)

i = left; j = right;

x = items[(left + right) / 2];

qs ( items , i , right );

Пример 2: Метод сортировки Хоара на абстрактном функциональном языке.

let rec quicksort = function

| h::t -> quicksort ([ for x in t when x -> x])

@ [h] @ quicksort ([ for x in t when x>h -> x]);;

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

Рассматривая пример с быстрой сортировкой Хоара, можно увидеть, что помимо уже упомянутых отличий между вариантом на языке C и вариантом на абстрактном функциональном языке, есть ещё одно важное отличие: функция на C сортирует список значений типа int (целых чисел), а функция на абстрактном функциональном языке - список значений любого типа, который принадлежит к классу упорядоченных величин. Поэтому последняя функция может сортировать и список целых чисел, и список чисел с плавающей точкой, и список строк. Можно описать какой-нибудь новый тип. Определив для этого типа операции сравнения, возможно без перекомпиляции использовать quickSort и со списками значений этого нового типа. Это полезное свойство системы типов называется параметрическим или истинным полиморфизмом, и поддерживается большинством функциональных языков.

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

В языке C++ имеется такое понятие, как шаблон, которое позволяет программисту определять полиморфные функции, подобные quickSort. В стандартную библиотеку C++ STL входит такая функция и множество других полиморфных функций. Но шаблоны C++, как и родовые функции Ada, на самом деле порождают множество перегруженных функций, которые, кстати, компилятор должен каждый раз компилировать, что неблагоприятно сказывается на времени компиляции и размере кода. А в функциональных языках полиморфная функция quickSort - это одна единственная функция.

В некоторых языках, например в Ada, строгая типизация вынуждает программиста явно описывать тип всех значений и функций. Чтобы избежать этого, в строго типизированные функциональные языки встроен специальный механизм, позволяющий компилятору определять типы констант, выражений и функций из контекста. Этот механизм называется механизмом вывода типов. Известно несколько таких механизмов, однако большинство из них являются разновидностями модели типизации Хиндли-Милнера, разработанной в начале 80-х годов XX века. Таким образом, в большинстве случаев можно не указывать типы функций.

Модульность

Механизм модульности позволяет разделять программы на несколько сравнительно независимых частей (модулей) с чётко определёнными связями между ними. Тем самым облегчается процесс проектирования и последующей поддержки больших программных систем. Поддержка модульности не является свойством именно функциональных языков программирования, однако поддерживается большинством таких языков. Существуют очень развитые модульные императивные языки. В качестве примеров подобных языков можно привести Modula-2 и Ada-95.

Функции - это значения

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

Например, определив функцию возведения целого числа в квадрат как:

square :: Int -> Int square n = n * n

M ожем воспользоваться этой функцией для возведения в квадрат всех элементов списка

l2 = map square [1, 2, 3, 4] - результат - список [1, 4, 9, 16]

Чистота (отсутствие побочных эффектов)

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

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

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

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

Отложенные вычисления

Языки, использующие отложенные вычисления, называются нестрогими. Haskell - нестрогий язык, так же как, например, Gofer и Miranda. Нестрогие языки зачастую являются чистыми.

Очень часто строгие языки включают в себя средства поддержки некоторых полезных возможностей, присущих нестрогим языкам, например бесконечных списков. В поставке Standard ML присутствует специальный модуль для поддержки отложенных вычислений. А Objective Caml помимо этого поддерживает дополнительное зарезервированное слово lazy и конструкцию для списков значений, вычисляемых по необходимости.

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

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

ISWIM (If you See What I Mean). Функциональный язык-прототип. Разработан Ландиным в 60-х годах XX века для демонстрации того, каким может быть язык функционального программирования. Вместе с языком Ландин разработал и специальную виртуальную машину для исполнения программ на ISWIM’е. Эта виртуальная машина, основанная на вызове-по-значению, получила название SECD-машины. На синтаксисе языка ISWIM базируется синтаксис многих функциональных языков. На синтаксис ISWIM похож синтаксис ML, особенно Caml.

Scheme . Диалект Lisp’а, предназначенный для научных исследований в области computer science. При разработке Scheme был сделан упор на элегантность и простоту языка. Благодаря этому язык получился намного меньше, чем Common Lisp.

ML (Meta Language). Семейство строгих языков с развитой полиморфной системой типов и параметризуемыми модулями. ML преподается во многих западных университетах (в некоторых даже как первый язык программирования).

Standard ML . Один из первых типизированных языков функционального программирования. Содержит некоторые императивные свойства, такие как ссылки на изменяемые значения и поэтому не является чистым. При вычислениях использует вызов-по-значению. Очень интересная реализация модульности. Мощная полиморфная система типов. Последний стандарт языка — Standard ML-97, для которого существует формальные математические определения синтаксиса, а также статической и динамической семантик языка.

Caml Light и Objective Caml. Как и Standard ML принадлежит к семейству ML. Objective Caml отличается от Caml Light в основном поддержкой классического объектно-ориентированного программирования. Также как и Standard ML строгий, но имеет некоторую встроенную поддержку отложенных вычислений.

Miranda . Разработан Дэвидом Тернером, в качестве стандартного функционального языка, использовавшего отложенные вычисления. Имеет строгую полиморфную систему типов. Как и ML преподаётся во многих университетах. Оказал большое влияние на разработчиков языка Haskell.

Haskell . Один из самых распространённых нестрогих языков. Имеет очень развитую систему типизации. Несколько хуже разработана система модулей. Последний стандарт языка — Haskell-98.

Gofer (GOod For Equational Reasoning). Упрощённый диалект Haskell’а. Предназначен для обучения функциональному программированию.

Clean. Специально предназначен для параллельного и распределённого программирования. По синтаксису напоминает Haskell. Чистый. Использует отложенные вычисления. С компилятором поставляется набор библиотек (I/O libraries), позволяющих программировать графический пользовательский интерфейс под Win32 или MacOS.

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

Рубрика Программирование, компьютеры и кибернетика
Вид реферат
Язык русский
Дата добавления 15.04.2016
Размер файла 142,2 K

Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.

Министерство образования и науки Российской Федерации

Федеральное государственное автономное образовательное учреждение

высшего профессионального образования

филиал в г. Пятигорске.

РЕФЕРАТ

Выполнил(а): Сагиров М.Н.

Проверила: Битюцкая Н.И

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

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

Краткость и простота

Чистота (отсутствие побочных эффектов)

Отложенные вычисления (Lazy evaluation)

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

Список используемой литературы

Internet-ресурсы по функциональному программированию

Введение

Функциональное программирование ставит своей целью придать каждой программе простую математическую интерпретацию. Эта интерпретация должна быть независима от деталей исполнения и понятна людям, которые не имеют научной степени в предметной области. Архитектура языков программирования должна была быть максимально приближена к архитектуре компьютера. Компьютер состоит из центрального процессора и памяти. Поэтому программа должна была состоять из последовательности инструкций, выполняемых процессором и модифицирующих память. Функциональная программа представляет собой определения функций. Функции определяются через другие функции или рекурсивно - через себя. В процессе выполнения программы, функции получают параметры, вычисляют и возвращают результат, в случае необходимости вычисляя значения других функций. Почти каждый из нас так или иначе использовал функциональный подход к программированию. Возьмем к примеру, всем известный MicrosoftExcel. Записывая содержимое ячейки в виде, похожем на обычную математическую формулу, мы не задумываемся о действительном порядке вычислений этой формулы, возлагая эти функции на встроенный в Excel интерпретатор. А этот интерпретатор построен так, что правильный порядок вычисления этого выражения и, следовательно, правильный результат гарантированы. Как описывать вычисления на языке более близком человеку, чем компьютеру?". На этот вопрос призваны ответить универсальные функциональные языки программирования.

1. Просмотреть общее сведения и уровни функциональных языков программирования.

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

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

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

2. Рассмотрение истории развития функциональных языков программирования.

3. Обзор современных функциональных языков программирования

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

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

Функциональное программирование ставит своей целью придать каждой программе простую математическую интерпретацию. Эта интерпретация должна быть независима от деталей исполнения и понятна людям, которые не имеют научной степени в предметной области. Паулсон, Лоренс В 40-х годах нашего века были построены первые цифровые компьютеры. Самые первые модели этих компьютеров 'программировались' на машинных языках, посредством соединения плат проводками вручную или, в лучшем случае, путем установки в нужное положение сотен переключателей. Машинные языки плохо воспринимаются человеком, поэтому следующим шагом стало создание различных ассемблеров. В ассемблере машинные команды получают компактные мнемокоды типа LOAD, STORE, ADD и т.п. В конце 50-х годов сотрудник IBM Джон Бэкус решил, что записывать Формулы вида о к тому же эти формулы могут быть выполнены на любой машине, для которой есть специальная программа, которую назвали компилятором. Первый компилятор был создан для языка FORTRAN (FORmulaTRANslator - Транслятор Формул). В те дни компьютеры были очень дороги. Поэтому создатели первых языков программирования высокого уровня в погоне за эффективностью пошли по наиболее простому пути. Архитектура языков программирования должна была быть максимально приближена к архитектуре компьютера. Компьютер состоит из центрального процессора и памяти. Поэтому программа должна была состоять из последовательности инструкций, выполняемых процессором и модифицирующих память. На основе этого принципа был разработан так называемый императивный стиль программирования. Основными признаками императивных языков программирования являются ориентированность, в первую очередь, на последовательное исполнение инструкций оперирующих с памятью (присваиваний) и итеративные циклы. Но не это главное. Со времен возникновения FORTRAN-а прошло почти 50 лет. За это время были разработаны сотни намного более развитых императивных языков, таких как Pascal, C++, Ada, Java и т.д. Значительно усовершенствованы механизмы и методы императивного программирования. Однако идея, лежащая в его основе, остается прежней. Программы на этих языках описывают процесс последовательного, пошагового решения задачи. Как следствие, полученные программы слабо напоминают оригинальную спецификацию задачи, которая, как правило, не содержат никаких упоминаний о различных массивах, указателях и счетчиках. На протяжении последних 400 лет, центральным понятием математики является понятие функции. Математические функции выражают связь между параметрами (входом) и результатом (выходом) некоторого процесса. Так как вычисление -- это тоже процесс, имеющий вход и выход, функция - вполне подходящее средство задания вычислений. Именно этот простой принцип положен в основу функционального стиля программирования. Функциональная программа представляет собой определения функций. Функции определяются через другие функции или рекурсивно - через себя. В процессе выполнения программы, функции получают параметры, вычисляют и возвращают результат, в случае необходимости вычисляя значения других функций. Программируя на функциональном языке, программист не должен описывать порядок вычислений. Ему необходимо просто описать желаемый результат в виде системы функций. Почти каждый из нас так или иначе использовал функциональный подход к программированию. Возьмем к примеру, всем известный MicrosoftExcel. Записывая содержимое ячейки в виде, похожем на обычную математическую формулу, мы не задумываемся о действительном порядке вычислений этой формулы, возлагая эти функции на встроенный в Excel интерпретатор. А этот интерпретатор построен так, что правильный порядок вычисления этого выражения и, следовательно, правильный результат гарантированы. Фактически, вся таблица представляет собой набор функций и констант (которые, в общем, тоже функции), определенных друг через друга.

Другим простым примером могут послужить языки запросов к базам данных. В большинстве своем эти языки используют один из двух подходов. В языках, основанных на реляционной алгебре, результат записывается в терминах операций над таблицами, демонстрируя тем самым явно императивный подход. Языки же, основанные на реляционном исчислении (например, всем известный SQL или QBE), напротив, описывают только результат, являясь тем самым по сути функциональными. По мере развития вычислительной техники, компьютерное время удешевляется, поэтому особую важность приобретает вопрос "Как описывать вычисления на языке более близком человеку, чем компьютеру?". На этот вопрос призваны ответить универсальные функциональные языки программирования, программы на которых гораздо больше напоминают изначальную спецификацию задачи чем программы, написанные с помощью императивных языков программирования.


Лекции


Лабораторные


Справочники


Эссе


Вопросы


Стандарты


Программы


Дипломные


Курсовые


Помогалки


Графические

Доступные файлы (1):

hugs.doc

1. Общие сведения о функциональном программировании 9

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

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

1.2.1. Краткость и простота 13

1.2.2. Строгая типизация 16

1.2.3. Модульность 18

1.2.4. Функции — это значения 18

1.2.5. Чистота (отсутствие побочных эффектов) 19

1.2.6. Отложенные (ленивые) вычисления 20

2. Основы работы с HUGS 98 21

2.1. Панель инструментов HUGS 98 22

2.2. Команды консоли HUGS 98 25

2.3. Дополнительные возможности для отладки 28

2.3.1. Просмотр классов 30

2.3.3. Просмотр конструкторов типов 33

2.3.4. Просмотр иерархии классов 34

Работа 1
Основы функционального программирования 36

Работа 2
Изучение файла Prelude.hs 40

Работа 3
Углублённое изучение возможностей языка Haskell 43

Работа 4
Выполнение сложных задач Искусственного Интеллекта 48

Список литературы 51

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

Б. Интернет-ресурсы по функциональному прог­рам­ми­ро­ва­нию 57

В. Параметры ИС HUGS 98 58

Предисловие

Традиционно на кафедре кибернетики МИФИ преподавались ос­новы функционального программирования на примере языка Lisp, разработанного в середине XX века, а лабораторные ра­бо­ты проводились на версии -Lisp [1]. Однако со времени раз­ра­бот­ки языка Lisp было создано множество новых теоретических ме­ханизмов, формализмов и методологий функционального прог­раммирования, венцом чего стала разработка уни­фи­ци­ро­ван­ного стандарта Haskell-98, ставшего в последующем фун­к­ци­о­нальным языком программирования [2].

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

Теоретические основы функционального программирования бы­ли заложены ещё в 20-х годах XX столетия после разработки та­ких мощных вычислительных формализмов, как ком­би­на­тор­ная логика и λ-исчисление [6]. Впоследствии λ исчисление стало ба­зисом всех разработанных функциональных языков, начиная от первого функционального языка Lisp, заканчивая последней раз­работкой — языком Haskell-98.

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

Поэтому при помощи принципов, заложенных в фун­к­ци­о­наль­ном программировании, могут решаться такие задачи, как сим­вольные вычисления, вывод на знаниях, обработка фор­ма­ли­зо­ванных и естественных языков, выявление знаний в базах дан­ных, создание общающихся между собой программных систем (аген­тов), а также некоторые другие. Все эти задачи являются тра­диционными для искусственного интеллекта [7], [8].

Лабораторный практикум состоит из двух частей. Первая часть практикума посвящена описанию инструментального сред­ства HUGS 98, которое является бесплатным программным ком­плексом для программирования на языке Haskell. Кроме то­го, в первой части приведены базовые сведения о парадигме фун­кционального программирования — его история, назначение и свойства.

Также выражаю благодарность своим коллегам — Клочкову Андрею и Мирошкину Алексею за их помощь и особые советы, которые помогли сделать курс и лабораторный практикум более лёгким для понимания. Особенную благодарность выражаю своей жене Елене за её понимание и поддержку.

Введение

Созданная в 1998 году спецификация языка Haskell (наз­ван­но­го так в честь учёного Хаскелла Карри, одного из ос­но­во­по­лож­ников функционального программирования) нашла не­обы­чай­но широкую поддержку в научных кругах, в первую очередь, Ев­ропы и Японии. В связи с этим буквально за несколько ме­ся­цев различными исследовательскими группами и ком­мер­чес­ки­ми компаниями было создано несколько реализаций языка Haskell как в виде интерпретаторов, так и в виде компиляторов — бес­платных и коммерческих.

Наиболее интересным инструментальным средством (ИС), ко­торое используется во многих университетах мира при изу­че­нии основ функционального программирования, является ИС HUGS 98, включающее в себя собственно интерпретатор языка Haskell стандарта 1998 года (далее Haskell-98), а также ин­тег­ри­ро­ванную среду программирования.

Кроме того, ИС HUGS 98 является абсолютно бесплатным прог­раммным средством и может быть свободно получено через Ин­тернет по адресу www.haskell.org. Это дополнительно спо­соб­с­твует распространению рассматриваемого ИС в качестве сред­­ства для обучения, хотя оно и обладает некоторыми не­дос­тат­ка­ми по сравнению с коммерческими реализациями языка Haskell 98.
^

1. Общие сведения о функциональном программировании

Прежде чем начать описание собственно функционального прог­раммирования, необхо­димо обратиться к истории науки о прог­раммировании.

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

Однако даже ассемблеры не могли стать инструментом, удоб­ным для пользования, так как мнемокоды всё ещё оставались слиш­ком сложными, тем более что всякий ассемблер был жёс­т­ко связан с архитектурой компьютера, на котором он ис­пол­нял­ся. Таким образом, следующим шагом после ассемблера стали так называемые им­пе­ра­тив­ные языки высокого уровня (BASIC, Pascal, C, Modula и прочие, включая объектно-ори­ен­ти­рован­ные). Императивными такие языки были названы по причине то­го, что глав­ным их свойством является ориентированность, в пер­вую очередь, на пос­ле­до­ва­тель­ное исполне­ние инструкций, опе­рирующих с памятью (т.е. присваиваний), и итеративные цик­­лы. Вызо­вы функций и процедур, даже рекурсивные, не из­бав­ляли такие языки от яв­ной импера­тивности (пред­пи­са­ния) [9].

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

Математические функции выражают связь между па­ра­мет­ра­ми (входом) и результатом (вы­ходом) некоторого процесса. Так как вычисление (а в общем случае и программа) — это тоже про­цесс, имеющий вход и выход, функция является вполне под­хо­дящим и адекватным средством описания вы­чис­ле­ний. Имен­но этот простой принцип положен в основу функциональной па­ра­дигмы и фун­к­ционального стиля программирования. Фун­к­ци­о­нальная программа представляет со­бой набор определений фун­кций. Функции опре­деляются через другие функции или ре­кур­сивно, т.е. через самих себя. В процессе выполне­ния прог­рам­мы функции получают па­ра­метры, вычисляют и возвращают ре­зультат, в слу­чае необходимости вычисляя значения дру­гих функ­ций. Программируя на функциональ­ном языке, прог­рам­мист не должен опи­сы­вать порядок вычислений. Ему не­об­хо­ди­мо просто описать желаемый результат в виде сис­темы функ­ций [10], [11].

Особо следует подчеркнуть, что функцио­нальное прог­рам­ми­ро­вание, равно как и логическое программирование, нашло боль­шое применение в искусственном интеллекте и его приложениях [7], [8], [12].

В качестве базовой литературы, раскрывающей вопросы функ­ционального программирования, можно посоветовать такие ос­новополагающие работы, как [1], [3], [4].

Расширенный список литературы по функциональному прог­рам­мированию приведён в конце лабораторного практикума.

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

Программирование и разработка

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

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

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

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

Давайте определим эту парадигму программирования (и парадигмы в целом), а затем рассмотрим некоторые плюсы и минусы функционального программирования.

Что такое парадигма программирования?

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

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

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

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

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

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

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

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

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

  • Чистые функции — функциональное программирование использует чистые функции. Это функции, которые не изменяются, дают надёжные результаты и всегда дают одинаковый результат для одного и того же ввода. Они не вызывают неожиданных результатов или побочных эффектов и абсолютно предсказуемы независимо от внешнего кода.
  • Неизменяемость — это принцип, согласно которому после того, как вы установили значение для чего-либо, это значение не изменится. Это устраняет побочные эффекты или неожиданные результаты, поскольку программа не зависит от состояния. Таким образом, функции всегда работают одинаково при каждом запуске; это чистые функции.
  • Дисциплинированное состояние — новые ценности могут быть созданы, поэтому есть некоторые состояния, которые могут измениться в этом смысле, но это глубоко контролируемый процесс. Функциональное программирование стремится избежать общего состояния и изменчивости. Если состояние жёстко контролируется, его легче масштабировать и отлаживать, и вы получаете менее неожиданные результаты.
  • Ссылочная прозрачность — этот принцип основан на сочетании чистых функций и неизменности. Поскольку наши функции чисты и предсказуемы, мы можем использовать их для замены переменных и, следовательно, уменьшить количество выполняемых назначений. Если результат функции будет равен переменной, поскольку наши результаты предсказуемы, мы можем просто заменить переменную этой функцией.
  • Функции первого класса — этот принцип прост. Функциональное программирование очень высоко ценит определённые функции, функции первого класса. Следовательно, он поддерживает передачу целых функций между собой так же легко, как другие языки с переменными. Эти функции можно рассматривать как значения или данные в функциональном программировании.
  • Системы типов — поскольку функциональное программирование так сосредоточено на точности и предотвращении ошибок. Наличие статически типизированной системы имеет смысл. Это необходимо для того, чтобы убедиться, что каждый тип данных назначен правильно, строки — это строки, а числа с плавающей запятой — это числа с плавающей запятой, и предотвращает использование непредсказуемых переменных.

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

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

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

Плюсы

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

Минусы

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

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

Функциональное программирование намного старше объектно-ориентированного программирования, и в последние годы оно немного вернулось. Это возвращение в основном связано с языками из этого списка.

  • JavaScript. Хотя JavaScript не является чисто функциональным языком, у него есть много функций функционального программирования. Из-за этого программисты чаще, чем раньше, используют функциональное программирование на JavaScript, потому что оно может быть более полезным и стабильным в определённых сценариях по сравнению с объектно-ориентированными языками.
  • Clojure — это не совсем то, что нарицательное имя JavaScript, но это надёжный функциональный язык программирования, построенный на основе Lsip, который существует с 1950-х годов. Это означает, что он функционален до самого основания. Он работает на платформе Java и скомпилирован в байт-код JVM.
  • Haskell — ещё один чисто функциональный язык, разработанный для решения реальных, а не академических задач. Он не так стар, как Lisp, он был создан в 1990-х годах. Он использовался для нескольких популярных проектов, таких как оконный менеджер Xmonad.

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

Знакомство с функциональным программированием в Python, JavaScript и Java

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

Как же можно половчее переключиться от ООП к ФП?

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

По ходу статьи мы ответим на следующие вопросы:

  • Что такое функциональное программирование?
  • Как оно реализовано в различных языках?
  • Каковы его основные принципы?
  • Как оно используется в Python, JavaScript и Java?
  • Что стоит изучать далее?

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

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

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

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

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


Визуальное представление функций в ФП

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

К наиболее распространенным областям, применяющим ФП, относятся проектирование ИИ, алгоритмы классификации в МО, финансовые программы, а также продвинутые модели математических функций.

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

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

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

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

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

Функциональные языки:

    : это наиболее популярный язык среди функциональных программистов. В нем реализована защита памяти, отличный сбор мусора, а также повышенная скорость, обусловленная ранней компиляцией машинного кода. Его богатая статическая система типов дает вам доступ к уникальным алгебраическим и полиморфным типам, которые делают процесс программирования более эффективным, а код более читаемым. : этот язык, как и его потомок, Elixir, заняли нишу лучших функциональных языков для параллельных систем. Несмотря на то, что в популярности он уступает Haskell, его нередко используют для бэкенд-программирования. В последнее время Erlang начал завоевывать внимание в сфере масштабируемых мессенджеров, таких как WhatsApp и Discord. : это ориентированный на функциональную парадигму диалект Lisp, который работает на виртуальной машине Java (JVM). Будучи преимущественно функциональным языком, он поддерживает как изменяемые, так и неизменяемые структуры данных, но при этом все же менее строг в функциональном плане, чем другие. Если вам нравится Lisp, то вы также полюбите и Clojure. : этот язык аналогичен Haskell (они находятся в одной языковой группе), но имеет меньше расширенных возможностей. Кроме того, в нем реализована слабая поддержка объектно-ориентированных конструкций.

Языки с функциональными возможностями

    : этот язык поддерживает как ООП, так и ФП. Его наиболее интересная особенность в наличии строгой системы статической типизации, как в Haskell, которая помогает создавать строгие функциональные программы. При проектировании Scala среди прочих стояла задача решить многие критические проблемы Java, поэтому данный язык очень подходит для Java-разработчиков, желающих попробовать функциональное программирование.
  • JavaScript: несмотря на то, что приоритет в этом языке не на стороне функциональной парадигмы, JavaScript уделяет ей немало внимания в связи со своей асинхронной природой. В нем также поддерживаются такие важные функциональные возможности, как лямбда выражения и деструктуризация. Вместе эти атрибуты выделяют JS как ведущий язык для ФП.
  • Python, PHP, C++: эти мультипарадигмальные языки тоже поддерживают функциональное программирование, но уже в меньшей степени, чем Scala и JavaScript.
  • Java: этот язык относится к языкам общего назначения, но приоритет в нем отдается ООП, основанному на классах. Несмотря на то, что добавление лямбда выражений в некотором смысле помогает реализовывать более функциональный стиль, в конечном итоге Java остается языком ООП. Он позволяет заниматься функциональным программированием, но при этом в нем недостает ключевых элементов, которые бы оправдывали его освоение именно с этой целью.

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

Переменные и функции

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

Чистые функции

Для чистых функций характерны два свойства:

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

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

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

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

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

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

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

Рекурсия

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

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

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

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

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

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

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

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

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

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

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

Попробуйте оформлять весь код на уровне модулей и переключайтесь на классы только по мере необходимости.

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

Чистые и неизменяемые функции

Многие из встроенных в Python структур данных являются неизменяемыми по умолчанию:

  • integer;
  • float;
  • Boolean;
  • string;
  • Unicode;
  • tuple.

Кортежи особенно полезны при использовании в качестве неизменяемой формы массива.

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

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

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

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

Функции в качестве объектов

Передача функции в качестве параметра

Возвращение функции из другой функции

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

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

На строке 4 мы определяем функцию compose2 , получающую две функции в качестве аргументов f и g .
На строке 5 мы возвращаем новую функцию, представляющую композицию из f и g .

В завершении на строке 6 мы возвращаем результаты этой композиции функций.

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

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

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

Чистые и неизменяемые функции

Чтобы начать создание чистых функций в JS, нам понадобится использовать функциональные альтернативы стандартному поведению, такие как const , concat и filter .

Стандартное ключевое слово let определяет изменяемую переменную. Если вместо него для объявления использовать const , это гарантирует нам неизменность переменной, так как переназначить ее уже не получится.

Функциональные альтернативы нам также нужно использовать для управления массивами. Стандартным способом добавления элемента в массив является метод push() . К сожалению, этот метод изменяет начальный массив, в связи с чем не считается чистым.

Но у нас есть его функциональный эквивалент — concat() . Вот он уже возвращает новый массив, который содержит все начальные элементы вместе с добавленным. В этом случае сам начальный массив остается неизменным.

Для удаления элемента из массива мы обычно используем методы pop() и slice() . Тем не менее они не относятся к функциональным, так как изменяют именно первичный массив. Вместо них мы берем метод filter() , который создает новый массив со всеми элементами, прошедшими проверку условия.

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

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

Присвоение функции к переменной

Добавление функции в массив

Передача функции в качестве аргумента

Возвращение функции из другой функции

Функциональная композиция

В JavaScript мы можем компоновать функции при помощи цепочек вызовов:

В качестве альтернативы можно передать выполнение функции в следующую функцию:

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

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

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

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

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

Чистые и неизменяемые функции

В Java есть несколько неизменяемых структур данных:

Вы также можете создавать собственные неизменяемые классы при помощи ключевого слова final .

Ключевое слово final в классе предотвращает создание дочернего класса. Использование final для name и regNo делает невозможным изменение значений после построения объекта.

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

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

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

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

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

Java содержит интерфейс, java.util.function.Function , предоставляющий методы для композиции функций. Метод compose сначала выполняет переданную ему функцию ( multiplyByTen ), а затем передает возвращаемое значение внешней функции ( square ).

И наоборот — метод andThen выполняет сначала внешнюю функцию, а затем функцию из своих параметров.

На строках 1 и 2 мы сначала создаем две функции, square и multiplyByTen .
Затем на строках 5 и 8 мы делаем из них две композиции, multiplyByTenAndSquare и squareAndMultiplyByTen , каждая из которых принимает два аргумента (удовлетворяя условие square ).

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

Что изучать дальше

Сегодня мы пробежались по наиболее общим принципам функционального программирования и узнали, как они проявляются в Python, JavaScript и Java.

Одним из ведущих функциональных языков, переживающим этап возрождения, является Scala. Многие технологические гиганты, такие как Twitter и Facebook, начали использовать этот язык и уже ищут программистов с соответствующими навыками, поэтому рекомендуем выбрать в качестве следующего этапа на пути освоения ФП именно Scala.

Читайте также: