Язык программирования Lisp¶
Lisp (от англ. LISt Processing — «обработка списков») — это семейство языков программирования, основанных на представлении программ в виде списков, что обеспечивает их однородность с данными. Lisp является одним из старейших высокоуровневых языков программирования, уступая по возрасту только Fortran. Отличается мощной системой макросов, динамической типизацией, поддержкой функционального программирования и автоматическим управлением памятью (сборкой мусора). Ключевая особенность — гомоиконичность, при которой код программы может быть прочитан, изменён и сгенерирован как структура данных самого языка.
¶История
¶Создание и ранние годы
Lisp был разработан Джоном Маккарти в 1958 году в Массачусетском технологическом институте (MIT). Первоначальная реализация, Lisp I, была создана для символьных вычислений и задач искусственного интеллекта (ИИ). В 1960 году Маккарти опубликовал статью «Recursive Functions of Symbolic Expressions and Their Computation by Machine», где формально описал язык. В 1962 году появился Lisp 1.5 — первый стандартизированный диалект, включавший интерпретатор и компилятор.
¶Развитие в 1970–1980-х годах
В 1970-х годах возникли несколько влиятельных диалектов: MacLisp (MIT, 1966), Interlisp (Xerox PARC, 1968) и Scheme (MIT, 1975, разработан Гаем Стилом и Джеральдом Сассманом). Scheme ввёл лексическую область видимости, замыкания и хвостовую рекурсию, став популярным в образовании. В 1980-х годах для нужд ИИ был создан Common Lisp (ANSI X3J13, 1984–1994), объединивший лучшие черты MacLisp, Interlisp и других диалектов. Common Lisp стал стандартом де-факто для коммерческих проектов на Lisp.
¶Современный период
В 1990–2000-х годах интерес к Lisp снизился из-за роста популярности языков общего назначения (C++, Java, Python). Однако язык продолжал использоваться в академической среде и специализированных областях. В 2000-х годах появились новые диалекты: Clojure (2007, Рич Хики), работающий на виртуальной машине Java (JVM), и Racket (2010, ответвление от Scheme). Clojure привлёк внимание сообщества Java-разработчиков благодаря интеграции с экосистемой JVM и поддержке параллелизма. В 2020-х годах Lisp остаётся нишевым, но востребованным в ИИ, обработке естественного языка, разработке экспертных систем и метапрограммировании.
¶Классификация
¶Основные диалекты
- Common Lisp — мультипарадигмальный стандарт (ANSI), поддерживает функциональное, императивное и объектно-ориентированное программирование (CLOS). Включает обширную стандартную библиотеку.
- Scheme — минималистичный диалект с акцентом на чистоту функционального стиля и формальную семантику. Используется в образовании и исследованиях.
- Clojure — современный диалект для JVM, .NET (ClojureCLR) и JavaScript (ClojureScript). Поддерживает неизменяемые структуры данных и параллелизм на основе Software Transactional Memory (STM).
- Emacs Lisp — встроенный язык текстового редактора GNU Emacs, используемый для настройки и расширения его функциональности.
- Racket — диалект с мощной системой макросов и поддержкой создания собственных языков на основе Lisp.
¶По парадигме
Lisp поддерживает несколько парадигм программирования:
- Функциональное программирование — функции как объекты первого класса, рекурсия, отображение (map), фильтрация (filter), свёртка (reduce).
- Императивное программирование — последовательное выполнение, присваивание, циклы (в Common Lisp —
do,loop). - Объектно-ориентированное программирование — через Common Lisp Object System (CLOS) или встроенные средства в Clojure (defrecord, deftype).
- Метапрограммирование — макросы, позволяющие генерировать код на этапе компиляции.
¶Особенности языка
¶Синтаксис
Синтаксис Lisp основан на S-выражениях (symbolic expressions): (оператор аргумент1 аргумент2 ...). Например: ``lisp (+ 1 2) ; возвращает 3 (defun square (x) (* x x)) ; определение функции ` Все конструкции, включая управляющие структуры (if, cond, loop), являются выражениями, возвращающими значение. Комментарии начинаются с ;`.
¶Типы данных
Lisp поддерживает динамическую типизацию. Основные типы:
- Атомы: числа (целые, с плавающей точкой, рациональные), символы, строки, булевы значения (
tиnil). - Списки: упорядоченные коллекции, построенные из ячеек cons (cons cells). Пример:
(1 2 3)— список из трёх элементов. - Векторы: массивы фиксированной длины, доступ по индексу.
- Хеш-таблицы: ассоциативные массивы.
- Функции: объекты первого класса, могут быть переданы как аргументы или возвращены из других функций.
¶Макросы
Макросы — ключевая особенность Lisp, позволяющая расширять синтаксис языка. Макрос получает код на этапе компиляции, преобразует его и возвращает новый код. Пример макроса when в Common Lisp: ``lisp (defmacro when (condition &body body) (if ,condition (progn ,@body))) ``` Макросы позволяют реализовывать предметно-ориентированные языки (DSL), например, для веб-разработки (Hunchentoot) или обработки данных.
¶Управление памятью
Lisp использует автоматическое управление памятью (сборку мусора). В Common Lisp и Clojure применяются поколенческие и параллельные сборщики мусора. В Emacs Lisp — простой сборщик на основе подсчёта ссылок.
¶Применение
¶Искусственный интеллект и экспертные системы
Lisp исторически был основным языком для ИИ. На нём написаны:
- MYCIN (1970-е) — экспертная система для диагностики инфекционных заболеваний.
- AM (1976) — система автоматического открытия математических закономерностей.
- Cyc (1984) — проект по созданию общей базы знаний (реализован на Cycl, диалекте Lisp).
¶Обработка естественного языка
Lisp используется в NLP-задачах: синтаксический анализ, машинный перевод, генерация текста. Примеры: система ELIZA (1966, Джозеф Вейценбаум) — один из первых чат-ботов, написанный на Lisp.
¶Разработка игр и графики
Lisp применялся в игровых движках (например, Jak and Daxter на GOAL — диалекте Lisp для PlayStation 2) и в системах компьютерной графики (Pixar использовала Lisp для рендеринга в 1980-х).
¶Веб-разработка
Clojure и Common Lisp используются для создания веб-приложений. Фреймворки: Hunchentoot (Common Lisp), Ring/Compojure (Clojure). Пример: система управления контентом Drupal (частично на Lisp в ранних версиях).
¶Образование
Scheme и Racket популярны в университетах для обучения основам функционального программирования и компиляции. Например, книга «Structure and Interpretation of Computer Programs» (SICP, 1984) использует Scheme.
¶Пример кода
Пример программы на Common Lisp, вычисляющей факториал числа: ```lisp (defun factorial (n) (if (<= n 1) 1 (* n (factorial (- n 1)))))
(print (factorial 5)) ; выведет 120 ```
Пример на Clojure, использующий неизменяемые структуры данных: ```clojure (defn factorial [n] (reduce * (range 1 (inc n))))
(println (factorial 5)) ; выведет 120 ```
¶Интересные факты
- Lisp был первым языком, реализовавшим сборку мусора (1960).
- В 1970-х годах существовали специализированные Lisp-машины (Symbolics, Lisp Machines Inc.), аппаратно оптимизированные для выполнения Lisp-кода.
- Язык оказал влияние на многие современные языки: Python (списковые включения, лямбда-функции), JavaScript (замыкания, функции как объекты), Ruby (блоки, динамическая типизация).
- В 2019 году Common Lisp занял 36-е место в рейтинге TIOBE, а Clojure — 41-е.
¶Критика
Основные недостатки Lisp:
- Синтаксис на основе скобок — воспринимается как неудобный для чтения и написания больших программ.
- Динамическая типизация — может приводить к ошибкам времени выполнения, которые в статически типизированных языках обнаруживаются на этапе компиляции.
- Ограниченная экосистема — меньше библиотек и инструментов по сравнению с Java, Python или JavaScript.
- Производительность — в некоторых реализациях (особенно интерпретируемых) уступает компилируемым языкам, хотя современные компиляторы Common Lisp (SBCL) генерируют эффективный машинный код.
¶Источники
- McCarthy, J. (1960). «Recursive Functions of Symbolic Expressions and Their Computation by Machine, Part I». Communications of the ACM.
- Steele, G. L. (1990). Common Lisp the Language, 2nd Edition. Digital Press.
- Abelson, H., Sussman, G. J. (1984). Structure and Interpretation of Computer Programs. MIT Press.
- Hickey, R. (2008). «The Clojure Programming Language». Proceedings of the 2008 Symposium on Dynamic Languages.
- Стандарт ANSI X3J13 (1994). Common Lisp: The Language Specification.
- TIOBE Index (2023). «Lisp Programming Language Ranking».