суббота, 12 мая 2007 г.

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

Большинство языков программирования, повсеместно используемых для разработки программного обеспечения, использует императивную парадигму программирования. Это значит, что процесс программирования представляет собой перечень инструкций или команд, которые изменяют состояние программы. Императивный подход имеет много общего с естественными языками, поэтому он достаточно понятен для понимания, и языки программирования базирующиеся на нем легче поддаются изучению.
В противовес императивной парадигме как правило противопоставляют декларативный подход. Суть подхода состоит в том, что программа представляет собой не набор команд, а описание действий, которое не предполагает такой строгой последовательности и ориентировано прежде всего на описание желаемого результата. Такой подход существенно проще и прозрачнее формализуется математическими средствами и, как следствие требует для понимания гораздо более высокую математическую подготовку. Одним из путей развития декларативной парадигмы стал функциональный подход к программированию.
Функциональный подход базируется на стиле программирования, при использовании которого в программах описывается способ решения поставленной задачи посредством вычисления значений функций с одним или несколькими аргументами, которые также можно рассматривать как функции. Любая функция представляет собой конструкцию языка, которая описывает правила преобразования своего аргумента в результат. Функцию, принимающую в качестве аргументов другие функции или возвращающую другую функцию в качестве результата, часто называют функцией высшего порядка. С теоретической точки зрения любая функция при функциональном подходе является функцией высшего порядка.
Благодаря тому что выражения в функциональном программировании очень схожи с выражениями в естественной математике, программы написанные на функциональных языках в большинстве случаев короче и нагляднее, чем те же самые программы на традиционных императивных языках. Кроме того, данная особенность достигается еще и посредством того, что функциональные языки являются более абстрактными по отношению к особенностям вычислительной техники, и для решения задачи используют подходы максимально приближенные к математическим вычислениям. Функциональные программы не содержат операторов присваивания, а переменные, получив однажды значение, никогда не изменяются. Именно по этой причине все операции с памятью выполняются автоматически.
Как правило каждому выражению (константа, переменная, функция) функционального языка поставлен в соответствие тот или иной тип. Такая система типизации в языках функционального программирования называется системой сильной типизации, а сам язык - языком с сильной типизацией. При этом многие функциональные языки имеют механизм выводимости типов (type inference), который позволяет определять типы констант, выражений и функций из контекста. То есть, если не задан тип переменной, входящей в состав выражения, то он может быть автоматически выведен на основании типов других переменных, которые входят в состав данного выражения. По этой причине типы используемых функций в некоторых случаях можно не указывать. Механизм выводимости типов не является исключительной особенностью функциональных языков, он так же существует и в некоторых современных императивных языках, однако впервые подобная возможность была реализована именно в функциональных языках.
В чистом функциональном программировании оператор присваивания отсутствует, а используемые переменные, являются просто псевдонимами для выражений. Именно по этой причине они не могут быть изменены или уничтожены. Благодаря этой особенности все функции свободны от побочных эффектов. Кроме того независимость и произвольный порядок выполнения функций делает функциональный подход удобным для параллельных вычислений.
Еще одной особенностью чистых функциональных языков является наличие механизма отложенного вычисления. В этом случае аргумент вычисляется, только если он нужен для вычисления результата. Такой поход иначе известен как «ленивые» вычисления, и у некоторых функциональных языков присутствует даже специальное ключевое слово lazy, которое описывает выражение, вычисляемое по необходимости. Следует отметить что механизм отложенного вычисления реализован не во всех функциональных языках.
Программы реализованные с помощью функциональных языков как правило работают медленнее чем аналоги, использующие императивный подход, однако они могут решать более абстрактные задачи с меньшими трудозатратами и являются весьма эффективными при реализации символьной обработки и анализе текстов. Помимо этого функциональный подход дает возможность прозрачного моделирования текста программ математическими средствами поэтому он активно используется в академических целях.
Впервые функциональный подход подход был воплощен в языке LISP. Основной задачей данного языка является символьная обработка данных. В своей основе LISP - это язык списков. Все в LISP, от данных до кода приложения, является списком. Хотя LISP не является строго функциональным языком, так как существующие в нем императивные свойства лишают его права так называться в строгом смысле слова, многие идиомы и функциональные возможности LISP имеют сильный функциональный привкус. Этот язык дал развитие большому количеству различных диалектов, наиболее распространенными из которых являются Common Lisp и Scheme, которые очень активно используются в наши дни.
Дальнейшим развитием функционального программирования стало появление семейства языков ML (Meta Language). Этот язык был задуман как инструмент для научных и образовательных учреждений, предназначенный для построения формальных доказательств в системе логики для вычислимых функций. Однако возможность практического применения языка для промышленных целей, к примеру для символьных вычислений спровоцировало пересмотр его концепции, что явилось причиной появления различных диалектов, таких как Standard ML, CaML Light и Objective CaML. К сожалению данное семейство также не является чисто функциональным.
Первым чистым функциональным языком стал язык SASL (сокр. от St. Andrews Static Language) в далеком 1972 году, который позже перерос в KRC (Kent Recursive Calculator). В свою очередь KRC дал развитие новому языку – Miranda, который используется и в наше время. Язык Miranda разрабатывался в качестве стандартного функционального языка. Сейчас он преподаётся во многих университетах, и так же как и ML и LISP оказал большое влияние на развитие функционального подхода.
В наше время к чистым функциональным языкам программирования, которые получили развитие и используются не только в академических целях можно отнести Haskell и Clean. Haskell является наиболее распространённым чисто функциональным языком программирования. Последний стандарт языка, по праву стал стандартом функционального программирования — Haskell-98. Язык Clean намного меньше распространен, чем Haskell, однако его синтаксис несильно отличается от синтаксиса Haskell. Главное отличие этих языков заключается в способе вычислений выражений.
Помимо всего этого функциональный подход получил огромное развитие в мультипарадигменных языках, сочетающих в себе различные подходы, и языках не являющихся чисто функциональными. Так к примеру Erlang - язык сочетает в себе функциональную сущность и понятие процессов. Идеологие данного языка является выражение "всё есть процесс" Он активно используется для разработок разного рода распределённых систем. Язык Scala сочетает возможности функционального и объектно ориентированного программирования, и имеет реализацию для платформы JVM. Nemerle является высокоуровневым компилируемым языком программирования для .NET и использует функциональный, объектно-ориентированный и императивный подходы. Python – язык, который по сути является объектно-ориентированным, использует помимо всего особенности и других парадигм, в том числе и функциональную. Python используется в различных качествах: как основной язык реализации, для создания расширений, для интеграции приложений. Подобно ему, существует большое количество различных языков, использующих в той или иной мере функциональный подход.
Функциональный подход это не альтернатива императивному. Это просто другой взгляд на теорию программирования, со своей культурой, теорией и спецификой, который обладает как преимуществами так и недостатками, присущими ему. Поэтому нет смысла сравнивать эти подходы или противопоставлять, гораздо лучше их совместить во благо разрабатываемых всеми нами программных проектов;)

Литература, использованная при написании статьи:

Функциональное программирование для всех
Курс введение в теорию программирования. Функциональный подход
Курс основы функционального программирования
Основы функционального программирования
Лекции по функциональному программированию
Декларативное программирование
Сильные стороны функционального программирования
Описание языка Haskell
Мягкое введение в Haskell. Часть 1
Форумы RSDN
Википедия

Комментариев нет: