Пранскевичус Владислав Александрович

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

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

Введение

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

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

Как известно, теоретические основы императивного программирования были заложены ещё в 1930-х годах Аланом Тьюрингом и Джоном фон Нейманом. Теория, положенная в основу функционального подхода, также родилась в 20-х — 30-х годах. В числе разработчиков математических основ функционального программирования можно назвать Моисея Шейнфинкеля и Хаскелла Карри, разработавших комбинаторную логику, и Алонзо Чёрча, создателя λ-исчисления.

Теория так и оставалась теорией, пока в конце 1950х годов Джон Маккарти и его студенты не разработали язык Lisp, который принято относить к функциональным языкам, хотя строго говоря он является мультипарадигменным языком, таким же как например Python. Lisp, разработанный Маккарти, дал начало целому семейству Lisp-подобных языков. На сегодняшний день существует два основных языка: это Scheme, используемый в основном в академической среде, и Common Lisp.

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

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

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

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

Язык Краткая характеристика Факториал
Common Lisp Мультипарадигменный: Функциональный, процедурный, объектно-ориентированный, метапрограммирование; динамическая типизация
(defun factorial (n)
   (if (<= n 1)
       1
       (* n (factorial (- n 1)))))
                
Python Мультипарадигменный: Функциональный, процедурный, объектно-ориентированный; динамическая duck типизация
def factorial(n):
    return reduce(lambda x, y: x*y, range(1, n+1))
                
Erlang Мультипарадигменный: Конкурентный, Функциональный; динамическая типизация
fac(0) -> 1;
fac(N) when N > 0, is_integer(N) -> N * fac(N-1).
                
OCaml Мультипарадигменный: императивный, функциональный, объектно-ориентированный; статическая строгая типизация

let rec fact n =
    if n =/ Int 0 then Int 1 else n */ fact(n -/ Int 1);;
val fact : Num.num -> Num.num = ⟨fun⟩
                
F# Мультипарадигменный: императивный, функциональный, объектно-ориентированный; статическая строгая типизация
let rec factorial n =
    match n with
    | 0 -> 1
    | _ -> n * factorial (n - 1)
                
Haskell Чисто функциональный, lazy, строгая статическая типизация
factorial :: Integer -> Integer
factorial n = product [1..n]
                

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

На сегодняшний день, функциональные языки и элементы функционального программированию все больше входят в мейнстрим и наблюдается явный тренд в сторону укрепления позиций ФП. Ранее такому сдвигу препятствовал фактор производительности -- зачастую приходилось выбирать более низкоуровневые и производительные языки программирования типа С++. Однако сейчас, когда существуют с одной стороны довольно продвинутые компиляторы функциональных языков и быстрые многоядерные компьютеры, фактор производительности отходит на задний план. В этом можно убедиться, посмотрев на тесты в Computer Languages Shootout. Можно заметить более высокую или сравнимую производительность ФЯ по сравнению с императивными языками на многих тестах.

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

Источники

  1. Основы функционального программирования на Wikibooks
  2. Lisp (programming language)
  3. Журнал "Практика функционального программирования"