Научная статья на тему 'ВЛИЯНИЕ ФУНКЦИОНАЛЬНОГО ПРОГРАММИРОВАНИЯ НА СОВРЕМЕННЫЕ ЯЗЫКИ ПРОГРАММИРОВАНИЯ'

ВЛИЯНИЕ ФУНКЦИОНАЛЬНОГО ПРОГРАММИРОВАНИЯ НА СОВРЕМЕННЫЕ ЯЗЫКИ ПРОГРАММИРОВАНИЯ Текст научной статьи по специальности «Компьютерные и информационные науки»

CC BY
313
54
i Надоели баннеры? Вы всегда можете отключить рекламу.
Ключевые слова
ФУНКЦИОНАЛЬНОЕ ПРОГРАММИРОВАНИЕ / С++ / PYTHON / HASKELL / ПАРАЛЛЕЛЬНЫЕ ВЫЧИСЛЕНИЯ / ЯЗЫКИ ПРОГРАММИРОВАНИЯ / ПАРАДИГМЫ ПРОГРАММИРОВАНИЯ / ЛЯМБДА-ФУНКЦИЯ / МОНАДИЧЕСКИЙ ИНТЕРФЕЙС / АСИНХРОННОСТЬ / ЛЕНИВАЯ ОЦЕНКА

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

Статья посвящена исследованию влияния функционального программирования на современные языки программирования. Автором обосновывается актуальность и значимость темы исследования. Современные языки программирования обладают большим набором различных инструментов и полезных функций, которые позволяют писать совершенно другой код на том же языке, для одной и той же задачи. Парадигма программирования - это, в первую очередь, способ мышления - то, как программист думает о представлении и обработке. Другими словами, парадигма программирования существует в сознании программиста; она не является частью языка. Разные языки могут в разной степени поддерживать определенную парадигму. В статье постулируется о том, что в настоящее время, функциональное программирование было актуальным направлением в разработке программного обеспечения с самых ранних дней, но приобрело новое значение в современную эпоху. Рассматриваются концепции, лежащие в основе функционального программирования. Заключается о том, что в современном мире, функциональное программирование переживает «ренессанс» из-за того, что функциональные языки позволяют писать декларативный, понятный и надежный программный код. Особый акцент делается на положении о том, что тренд на изучение и имплементацию концепций функциональной парадигмы существует в современных языках программирования общего пользования, что делает большинство современных языков программирования - мультипарадигмальными. В целом, анализ научной литературы позволил сделать вывод о том, что языки программирования движутся вперед и активно развиваются, накапливая новые, все более совершенные и удобные инструменты. Очевидно, что популярные языки, такие как Python и С ++, приобретают все большее количество функций, которые произошли от функционального программирования.

i Надоели баннеры? Вы всегда можете отключить рекламу.
iНе можете найти то, что вам нужно? Попробуйте сервис подбора литературы.
i Надоели баннеры? Вы всегда можете отключить рекламу.

THE INFLUENCE OF FUNCTIONAL PROGRAMMING ON MODERN PROGRAMMING LANGUAGES

The article is devoted to the study of the influence of functional programming on modern programming languages. The author substantiates the relevance and significance of the research topic. Modern programming languages have a large set of different tools and useful features that allow you to write completely different code in the same language for the same task. A programming paradigm is, first of all, a way of thinking - how the programmer thinks about representation and processing. In other words, the programming paradigm exists in the mind of the programmer; it is not part of the language. Different languages may support a particular paradigm to varying degrees. The article postulates that at present, functional programming has been a hot trend in software development since its earliest days, but has taken on a new meaning in the modern era. The concepts underlying functional programming are considered. It concludes that in the modern world, functional programming is experiencing a "renaissance" due to the fact that functional languages allow you to write declarative, understandable and reliable program code. Particular emphasis is placed on the position that the trend towards the study and implementation of the concepts of the functional paradigm exists in modern general-use programming languages, which makes most modern programming languages multi-paradigm. In general, the analysis of scientific literature led to the conclusion that programming languages are moving forward and actively developing, accumulating new, more and more advanced and convenient tools. Obviously, popular languages like Python and C++ are acquiring more and more features that have evolved from functional programming.

Текст научной работы на тему «ВЛИЯНИЕ ФУНКЦИОНАЛЬНОГО ПРОГРАММИРОВАНИЯ НА СОВРЕМЕННЫЕ ЯЗЫКИ ПРОГРАММИРОВАНИЯ»

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

Телегин Валентин Александрович

технический директор департамента мобильной разработки, ООО «Ростелеком Информационные Технологии», [email protected]

Статья посвящена исследованию влияния функционального программирования на современные языки программирования. Автором обосновывается актуальность и значимость темы исследования. Современные языки программирования обладают большим набором различных инструментов и полезных функций, которые позволяют писать совершенно другой код на том же языке, для одной и той же задачи. Парадигма программирования - это, в первую очередь, способ мышления - то, как программист думает о представлении и обработке. Другими словами, парадигма программирования существует в сознании программиста; она не является частью языка. Разные языки могут в разной степени поддерживать определенную парадигму. В статье постулируется о том, что в настоящее время, функциональное программирование было актуальным направлением в разработке программного обеспечения с самых ранних дней, но приобрело новое значение в современную эпоху. Рассматриваются концепции, лежащие в основе функционального программирования. Заключается о том, что в современном мире, функциональное программирование переживает «ренессанс» из-за того, что функциональные языки позволяют писать декларативный, понятный и надежный программный код. Особый акцент делается на положении о том, что тренд на изучение и имплемента-цию концепций функциональной парадигмы существует в современных языках программирования общего пользования, что делает большинство современных языков программирования - мультипарадиг-мальными. В целом, анализ научной литературы позволил сделать вывод о том, что языки программирования движутся вперед и активно развиваются, накапливая новые, все более совершенные и удобные инструменты. Очевидно, что популярные языки, такие как Python и С ++, приобретают все большее количество функций, которые произошли от функционального программирования. Ключевые слова: функциональное программирование, С++, Python, Haskell, параллельные вычисления, языки программирования, парадигмы программирования, лямбда-функция, монадический интерфейс, асинхронность, ленивая оценка.

Введение

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

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

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

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

1. Функции современных языков ФП

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

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

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

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

void update_user_balance(int user_id,

double (*update_fn)(double))

{

П ...

user->balance = update_fn(user->balance)\

и ...

X X

о

го А с.

X

го m

о

Рис. 1. Функции высшего порядка в чистом C

м о м

CJ

fO

es о es

о ш m

X

<

m О X X

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

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

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

1.2. Понимание списка и сопоставление шаблонов

Понимание списков позволяет кратко описать обработку или генерацию списков с использованием существующих. Miranda был одним из первых языков, использующих такой синтаксис, который был принят Haskell; позже подобные конструкции появились в "менее функциональных" языках, таких как Python, C # и Ruby [4].

Отметим, что в настоящее время, Haskell является лидером по внедрению новых функций.

Алгебраические типы данных. Эти типы также можно назвать ADT, типами сумм, дискриминационными объединениями, дизъюнктивными объединениями, копродуктами и, возможно, некоторыми другими умными терминами. Возможно, используется другое название для таких типов. В двух словах, это составной тип, содержащий дискриминантное поле (которое можно назвать тегом) вместе со связанными данными. Один пример в Haskell такого составного типа описывает возможные действия пользователя в гипотетической реализации приложения TodoMVC. Некоторые действия связаны с "полезной нагрузкой" (строка или идентификатор элемента) (см. рис. 2).

Несмотря на его простоту и полезность для моделирования объектов предметной области, ADT редко поддерживаются в полном масштабе в популярных языках и базах данных. Вот несколько примеров, реализующих похожие типы: Enum в Rust, закрытые классы в Kotlin, std: variant в C ++

data UserAction = Textlnput String EnterPressed EscPressed

CheckTodoItem Itemld Bool EditTodoItem Itemld String DeleteTodoItem Itemld ApplyFilter TodoFilter

Рис. 2. Возможные действия пользователя в гипотетической реализации приложения TodoMVC

Сопоставление с образцом - это синтаксическая конструкция, которая предоставляет доступ к данным структуры, состоящей из одной или нескольких альтернатив с разными наборами полей (тот самый ADT, алгебраический тип sum, enum, std: variant и т.д). Сопоставление шаблонов напоминает оператор переключения регистров, который все знают из императивных языков. Однако его главное преимущество заключа-

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

Сопоставление с образцом - это еще один метод, популяризированный в функциональных языках, где он оказался весьма полезным. Сейчас оно принято и интегрировано - в различных формах - в Python, Java, C #, Rust и другие популярные языки.

2. Использование ленивой оценки в ФП

2.2. Ленивая оценка

Отметим, что в большинстве языков программирования выполняется оценка. Одной из причин популярности lodash является его отличная производительность, большая часть которой основана на алгоритме ленивой оценки. Так, в большинстве языков программирования оценка выполняется, когда переменной присваивается значение; все аргументы оцениваются перед вызовом функции (строгие оценки). Альтернативный подход - «ленивый», подразумевающий, что вычисление откладывается до тех пор, пока значение не будет фактически использовано. Отложенная оценка позволяет работать с бесконечными структурами данных, писать декларативный код с определениями, расположенными в порядке, удобном для чтения, вместо порядка их оценки. Если используется подход DSL, отложенные вычисления помогают легко реализовать такие конструкции, как if-then-else (где значения будут оцениваться только в нужной вам ветке) [3].

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

Некоторые элементы «лени» можно найти в других языках. Даже в чистом C операторы && и || ленивы, поскольку они не вычисляют свой второй аргумент, если первый был соответственно оценен как 0 или 1. В языках более высокого уровня более распространенным термином является «отложенные оценки», которые реализуются с использованием функций генератора и ключевого слова «yield». Такие генераторы можно найти, например, в Python и Java.

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

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

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

2.2. Будущее (Future) и обещания (Promise, Deferred)

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

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

Promises были популяризированы главным образом из-за их адаптации и широкого использования в браузере. Выполнение JavaScript в браузере ограничено только одним потоком выполнения. Следовательно, блокировка во время ожидания HTTP-ответа, как и в случае с большинством платформ, привела бы к зависанию страницы и раздражению пользователей. Вот почему функции обратного вызова используются для обработки ответов на HTTP-запросы в браузере. В то же время комбинировать такие запросы не очень удобно, и появился термин «Ад обратного вызова» для описания кода, который стал неразборчивым из-за большого количества обратных вызовов. Обещания позволили частично решить проблему отправки параллельных запросов и последовательных цепочек запросов.

Так, во многих популярных языках (таких как C#, Java, JavaScript) обещания стали основным инструментом асинхронного программирования.

2.3. Монадический интерфейс и асинхронность

Названия многих конструкций и методов программирования в Haskell были заимствованы из теории категорий и других разделов математики. Один из таких терминов - Монада -стал объектом многих мемов и шуток о функциональном программировании. В Интернете есть много сообщений, объясняющих, что такое «Монады» в функциональных языках и как их использовать [5].

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

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

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

Появление async-await можно проследить до исследования, посвященного функциональному программированию в Haskell и ML, которое привело к появлению асинхронных рабочих процессов в F # (2007), а затем в C # (2011).

Заключение

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

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

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

Литература

1. Романова А.Э., Каюгина С.М. Языки программирования, их отличия и область применения в современном мире. // Сб. трудов Всеросс. науч.-практ. конф. «Неделя молодежной науки-2023» (Тюмень, 01-31 марта 2023 года). - Тюмень: Изд-во Государственного аграрного университета Северного Зауралья, 2023. - С. 1138-1141.

2. Герасимов А.П., Казаров С.Р., Тепляков П.В., Дудышев И.С. Языки программирования и их применение // Сб. ст. XXVI Межд. науч.-исслед. Конкурса «Студент года 2023» (Пенза, 05 апреля 2023 года). - Пенза: Наука и Просвещение (ИП Гуляев Г.Ю.), 2023. - С. 57-59.

3. Dean J., Ghemawat S. Mapreduce: simplified data processing on large clusters // Communications of the ACM. 2008. Vol. 51. No. 1. pp. 107-113.

4. Hammond K. Why parallel functional programming matters: Panel statement // Ada-Europe. 2011. Vol. 6652. Springer. pp. 201-205.

5. McKenna A., Hanna M., Banks E., Sivachenko A., Cibulskis K., Kernytsky A., Garimella K., Altshuler D., Gabriel S., Daly M. et al. The genome analysis toolkit: a mapreduce framework for analyzing next-generation dna sequencing data // Genome research. 2010. Vol. 20. No. 9. pp. 1297-1303.

The influence of functional programming on modern programming languages Telegin V.A.

Rostelecom Information Technologies

JEL classification: C10, C50, C60, C61, C80, C87, C90_

The article is devoted to the study of the influence of functional programming on modern programming languages. The author substantiates the relevance and significance of the research topic. Modern programming languages have a large set of different tools and useful features that allow you to write completely different code in the same language for the same task. A programming paradigm is, first of all, a way of thinking - how the programmer thinks about representation and processing. In other words, the programming paradigm exists in the mind of the programmer; it is not part of the language. Different languages may support a particular paradigm to varying degrees. The article postulates that at present, functional programming has been a hot trend in software development since its earliest days, but has taken on a new meaning in the modern era. The concepts underlying functional programming are considered. It concludes that in the modern world, functional programming is experiencing a "renaissance" due to the fact that functional languages allow you to write declarative, understandable and reliable program code. Particular emphasis is placed on the position that the trend towards the study and implementation of the concepts of the functional paradigm exists in modern general-use programming languages, which makes most modern programming languages multi-paradigm. In general, the analysis of scientific literature led to the conclusion that programming languages are moving forward and actively developing, accumulating new, more and more advanced and convenient tools. Obviously, popular languages like Python and C++ are acquiring more and more features that have evolved from functional programming.

Keywords: functional programming, C++, Python, Haskell, parallel computing, programming languages, programming paradigms, lambda function, monadic interface, asynchrony, lazy evaluation.

X X О го А С.

X

го m

о

м о м

CJ

References

1. Romanova A.E., Kayugina S.M. Programming languages, their differences and

scope in the modern world. // Sat. Proceedings of the All-Russian. scientific-practical. conf. "Youth Science Week-2023" (Tyumen, March 01-31, 2023). -Tyumen: Publishing House of the State Agrarian University of the Northern Trans-Urals, 2023. - P. 1138-1141.

2. Gerasimov A.P., Kazarov S.R., Teplyakov P.V., Dudyshev I.S. Programming

languages and their application // Sat. Art. XXVI Int. scientific research Competition "Student of the Year 2023" (Penza, April 05, 2023). - Penza: Science and Education (IP Gulyaev G.Yu.), 2023. - P. 57-59.

3. Dean J., Ghemawat S. Mapreduce: simplified data processing on large clusters //

Communications of the ACM. 2008 Vol. 51. No. 1.pp. 107-113.

4. Hammond K. Why parallel functional programming matters: Panel statement // Ada-

Europe. 2011 Vol. 6652. Springer. pp. 201-205.

5. McKenna A., Hanna M., Banks E., Sivachenko A., Cibulskis K., Kernytsky A.,

Garimella K., Altshuler D., Gabriel S., Daly M. et al. The genome analysis toolkit: a mapreduce framework for analyzing next-generation dna sequencing data // Genome research. 2010 Vol. 20. No. 9.pp. 1297-1303.

fO CS

iНе можете найти то, что вам нужно? Попробуйте сервис подбора литературы.

o

CS

o m m

X

<

m o x

X

i Надоели баннеры? Вы всегда можете отключить рекламу.