Факты и легенды о Лиспе

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


Лисп? Хм... Где-то я это уже слышал...

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

Кое-где Лисп до сих пор изучают в ВУЗах. Не знаю, входит ли он в программу подготовки ИТ-специалистов в Беларуси, но, думаю, даже если и не входит, будущим программистам стоит хотя бы поверхностно, с помощью этой статьи, ознакомиться с этим легендарным языком программирования.

Для начала, думаю, немного об истории его создания, хотя ей, пожалуй, стоило бы посвятить и отдельную статью. Дело в том, что создатель Лиспа Джон Маккарти в далёких пятидесятых годах предыдущего столетия занимался вопросами создания искусственного интеллекта. Вопросы эти и с позиции современной науки далеко не просты, а тогда были и вовсе практически за гранью понимания даже хорошо знакомого с программированием человека. Работавший в ту пору в Массачусетском технологическом институте Маккарти нуждался в таком языке программирования, с помощью которого можно было бы легко оперировать со словами обычного английского языка и с их последовательностями. Именно так и был создан язык с довольно оригинальным, на теперешний взгляд, синтаксисом, и названный LISP (нечто вроде акронима от List Processor - процессор списков).

Язык, созданный Маккарти в качестве средства построения искусственного интеллекта, стал популярен и в других областях. И это не случайно. Как совершенно справедливо написано на посвящённом Лиспу русскоязычном портале lisp.ru, "в 1960 Джон Маккарти опубликовал выдающуюся статью, в которой он сделал для программирования примерно то же, что Евклид когда-то сделал для геометрии. Он показал, как, имея в наличии только простые операторы и представление для функций, создать целый язык программирования". Впрочем, дата (1960 год) в данном случае довольно-таки условна - во многих источниках указывается, что оригинальная спецификация и первая версия Лиспа появились на два года раньше, то есть в 1958 году. Впрочем, плюс-минус пару лет для языка с таким богатым прошлым, как у Лиспа, особой погоды не делают.


Особенности Лиспа

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

Главной особенностью Лиспа можно считать тот факт, что он работает со списками. С другой стороны, этот язык программирования - функциональный. Я рассказывал о функциональном программировании на страницах "Компьютерных вестей", если конкретно - в статье "Знакомьтесь: функциональное программирование" (№24, 2008 год). С ещё одной стороны, современный Лисп поддерживает также объектно-ориентированное и процедурное программирование. Как может столько парадигм, довольно-таки различных по своей сути, ужиться в одном и том же языке программирования? Оказывается, в этом нет ничего особенно сложного.

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

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

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

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

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


Современный Лисп

Современные диалекты Лиспа и привнесли в него многие из популярных особенностей, например, то же объектно-ориентированное программирование, о котором Джон Маккарти на момент создания своего языка, конечно, даже и не слышал.

Самым популярным современным диалектом Лиспа является Common Lisp. Часто, когда пишут просто Lisp, имеют в виду именно Common Lisp, просто первое слово из его названия опускают для краткости.

Common Lisp - это стандартизованный язык, для которого существует немало компиляторов и интерпретаторов, многие из которых являются не просто бесплатными, а даже совершенно свободными программами. Главными отличиями Common Lisp от Лиспа "классического" является поддержка объектно-ориентированного программирования, без которой сложно представить любой современный язык программирования, а также развитая система макросов - то есть, языковых конструкций, которые можно применять для написания программы в привычном для программистов, использующих другие языки, стиле. Чтобы понять это отличие, посмотрите на листинги. В первом - программа для вычисления факториала на "традиционном" Лиспе, а во втором - она же, но уже на Common Lisp'е.

(defun factorial (n)
(if (<= n 1)
1
(* n (factorial (- n 1)))))


(defun factorial (n)
(loop for i from 1 to n
for fac = 1 then (* fac i)
finally (return fac)))

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

Для того чтобы представить себе отличия между Common Lisp и Scheme, приведу пример реализации вычисления факториала и для этого языка. Как видите, отличий от "классического" Лиспа в случае Scheme намного меньше, чем в случае Common Lisp:

(define (factorial n)
(if (= n 0)
1
(* n (factorial (- n 1)))))

В общем-то, помимо Common Lisp и Scheme, существует много других реализаций Lisp, используемых в современных ИТ-процессах. Самым удачным примером внедрения Lisp в качестве языка написания сценариев для серьёзной и большой программы можно считать язык AutoLisp, используемый в AutoCAD'е. Ещё один пример аналогичного, по своей сути, применения этого языка - это, опять-таки, встроенный язык сценариев, но уже в свободном аудиоредакторе Audacity, о котором когда-то на страницах "Компьютерных вестей" рассказывал маэстро Кристофер, а также в не менее свободном графическом редакторе Gimp. В Gimp'е, кстати, используется Scheme. Ну а если я не вспомню о Lisp'е в Emacs, то обидятся линуксоиды во главе с Михаилом Астапчиком (а возможно, и с самим Ричардом Столлмэном).


Резюмируем, пожалуй...

Газета не резиновая - она бумажная. Даже если вы читаете эту статью в электронном виде, на неё всё равно действуют те же ограничения по объёму, что и на статью в печатном варианте "Компьютерных вестей". Это я к чему? Это я к тому, что уже пора закругляться. Лисп - тема, безусловно, крайне интересная, однако хорошего, как говорится, понемножку, и пора уже подвести итоги тому, что было сказано выше.

Ну, во-первых, как вы сами можете убедиться, Лисп - это далеко не мёртвый язык программирования, несмотря на то, что возраст у него весьма и весьма почтенный даже для языка программирования. Сложно, конечно, сказать, кто сейчас "живее", если можно так выразиться, - Лисп или Фортран. Но в том, что Лисп живее того же Кобола, сомнений, думаю, не возникнет ни у кого.

Во-вторых, благодаря Common Lisp'у тот язык, о котором мы с вами так подробно и обстоятельно здесь говорили, не так уж и сильно отличается от "обычных" языков программирования - тех же C++, Java или PHP. Впрочем, Common Lisp, несмотря на свою популярность, это всё-таки уже не тот Лисп, который придумывал Джон Маккарти. Но пользоваться им всё-таки проще и приятнее, чем тем же Scheme. В-третьих, Лисп не так уж и неудобен - просто к нему нужно привыкнуть.

Если вас заинтересовал этот язык программирования, то вам прямая дорога на портал lisp.ru. Там вы найдёте массу информации по этому языку программирования.

Вадим СТАНКЕВИЧ

Версия для печатиВерсия для печати

Номер: 

39 за 2008 год

Рубрика: 

Software
Заметили ошибку? Выделите ее мышкой и нажмите Ctrl+Enter!