Современные языки, вроде Python и JavaScript, часто вдохновляются идеями, заложенными в Lisp более полувека назад. Это язык, который не просто «жив», а продолжает влиять на индустрию. Сегодня Lisp — это не только мощные научные исследования, но и живые, практичные инструменты, такие как редактор GNU Emacs, а также язык автоматизации чертежей AutoLISP в AutoCAD.
В этой статье мы погрузимся в его удивительную историю и разберемся, что делает его уникальным.
История создания: От математической абстракции до практического инструмента
История Lisp начинается в конце 1950-х годов, когда ученые только начинали задумываться о создании «мыслящих машин». Центральной фигурой в этой истории стал Джон Маккарти — математик, который также ввел в обиход сам термин «искусственный интеллект».
- Предпосылки В 1956 году на Дартмутском семинаре по ИИ Маккарти искал подходящий язык для работы со списками и символьными выражениями. Существующие языки (например, FORTRAN) для этого не подходили.
- Рождение идеи В 1958 году, работая в Массачусетском технологическом институте (MIT), Маккарти начал разработку нового языка. Его первоначальная цель была сугубо теоретической — создать алгебраический язык для обработки списков (LISt Processing), на основе λ-исчисления.
- Первые реализации Первые программы на Lisp запускались на мейнфрейме IBM 704. Именно архитектура этой машины подарила нам странные имена CAR и CDR.
- Публикация и признание В 1960 году Маккарти опубликовал статью «Recursive Functions of Symbolic Expressions and Their Computation by Machine, Part I», в которой формально описал язык.
- Lisp 1.5 (1960-1965) Эта версия стала основой для большинства последующих диалектов и закрепила популярность Lisp как языка выбора для исследователей ИИ.
- Путь к стандарту — Common Lisp К 1980-м годам число диалектов Lisp перевалило за сотню, что создавало проблемы с их совместимостью. Работа над диалектом началась в 1981 году по инициативе Управления перспективных исследовательских проектов (DARPA). В результате в 1984 году был опубликован первый документ по языку, а в 1994 году ANSI приняла стандарт для Common Lisp.
Первые программы на Lisp выполнялись на мейнфрейме IBM 704, который имел 36-битную архитектуру. Машинное слово делилось на две части: «адрес» (address) и «декремент» (decrement). Команды CAR (от «Contents of the Address part of Register») и CDR («Contents of the Decrement part of Register») извлекали соответствующую половину. Позже, когда Lisp перешёл на другие компьютеры, физическая связь с регистрами отпала, но имена остались.
Философия Языка
Lisp в первую очередь ассоциируется с функциональным программированием. Но, в отличие от «чистых» языков, Lisp предлагает прагматичный подход: он поощряет функциональный стиль, но не запрещает императивные приемы там, где они действительно удобны.
- «Код — это данные» В Lisp сам код программы и обрабатываемые им данные имеют единую структуру — S-выражения (S-expressions). Это позволяет программам легко генерировать и модифицировать свой собственный код, что делает Lisp невероятно гибким инструментом.
- Простота синтаксиса Вся программа, по сути, записывается как список вложенных списков. Синтаксис минималистичен: (имя_функции аргумент1 аргумент2 …).
- Динамическая типизация Lisp — язык с динамической типизацией, что ускоряет процесс написания и отладки кода.
- Интерактивная разработка (REPL) Программист может общаться с работающей программой в реальном времени, меняя ее поведение «на лету».
- Расширяемость Благодаря макросам, Lisp можно легко адаптировать под конкретные задачи, превращая его в язык, наиболее подходящий для вашей предметной области.
Lisp строит код, как вложенные списки, например `(+ 1 2)`. Хотя это префиксная запись, гибкость нотации Lisp позволяет встроить и другие парадигмы.
Связь с аппаратурой: машины, созданные для одного языка
Когда Lisp стали использовать для более сложных задач искусственного интеллекта, стало очевидно, что обычные компьютеры работают с ним недостаточно эффективно. Так родилась идеа специального «железа»:
- Лисп-машины (Lisp Machines) В середине 1970-х в MIT начали разрабатывать компьютер, архитектура которого была бы оптимизирована для выполнения Lisp-программ. Эти машины имели аппаратную поддержку ключевых операций: тегированной архитектуры, сборки мусора и работы со списками. Первые Lisp-машины, созданные в лаборатории искусственного интеллекта MIT, уже имели оконные системы. Вы могли запускать несколько программ в разных окнах, используя мышь — задолго до того, как это стало мейнстримом.
- CONS и CADR (MIT, 1973) Проект начали Ричард Гринблатт и Томас Найт. Первую машину назвали «CONS» — в честь функции создания списка. Настоящую известность получила её усовершенствованная версия, CADR, названная в честь встроенной Lisp-функции доступа ко второму элементу списка.
- Коммерциализация После ухода ключевых разработчиков из MIT образовались компании Symbolics и Lisp Machines Inc. (LMI). Их рабочие станции были настоящими технологическими флагманами. В этих машинах были впервые реализованы оконные системы, компьютерная мышь, эффективная сборка мусора, высококачественная лазерная печать и сетевые протоколы.
- Symbolics представила Dynamic Windows (1986) — оконную систему, которая вывела концепцию на новый уровень. Все элементы интерфейса были «живыми» Lisp-объектами, которые можно было исследовать и модифицировать прямо во время работы программы. Это стало прообразом современных интерактивных сред разработки. Принципы Dynamic Windows позже легли в основу стандарта CLIM, который до сих пор используется для создания сложных Lisp-приложений.
Основы синтаксиса Lisp (на примере Common Lisp)
- Базовый синтаксис и S-Выражения (единообразие кода и данных):
(+ 1 2)
(defun square (x) (* x x)) - Условные конструкции:
(cond ((> x 0) «Положительное») (t «Не положительное»))
(if (> x 0) (print «Положительное») (print «Отрицательное»)) - Переменные и функции:
(let ((x 10) (y 20)) (+ x y)) локальные
(defparameter *name* «John») глобальные
(defun factorial (n) (if (<= n 1) 1 (* n (factorial (- n 1))))) определение функции - Циклы и списки:
(loop for i from 1 to 5 do (format t «~a » i))
(dolist (item ‘(a b c)) (print item)) - Макросы (расширяющие синтаксис языка):
(defmacro measure-time (&rest body) …) - Ввод-вывод
(print «Hello world!»)
(format t «Hello, ~a!» «John»)
(setf user-input (read-line))
1. Базовый синтаксис и S-Выражения
Основой синтаксиса является S-выражение, которое может быть атомом (числом, строкой, символом) или списком.
;; Вызов функции: (функция аргумент...)
(+ 1 2) ;; Вернет 3
2. Условные конструкции
;; COND — как if-else if-else
(cond
((> x 0) "Число положительное")
((< x 0) "Число отрицательное")
(t "Ноль")) ;; t как else
;; IF для простых случаев
(if (evenp number)
(format t "Четное")
(format t "Нечетное"))
3. Определение переменных
;; Локальные переменные в блоке
(let ((x 10)
(y 20))
(+ x y)) ;; Вернет 30
;; Глобальные переменные
(defparameter *name* "John")
4. Функции
Функции — «граждане первого класса» — их можно передавать, возвращать и хранить в переменных.
;; Определение функции
(defun square (x)
(* x x))
(defun greet (name)
(format t "Hello, ~a!" name))
(defun factorial (n)
"Вычисляет факториал числа N рекурсивно."
(if (<= n 1)
1
(* n (factorial (- n 1)))))
5. Работа со списками
;; Создание списка
(setf my-list '(яблоко банан апельсин))
;; Основные функции
(car my-list) ;; Первый элемент -> 'яблоко
(cdr my-list) ;; Все кроме первого -> '(банан апельсин)
(cons 'груша my-list) ;; Добавление в начало -> '(груша яблоко банан апельсин)
6. Итерации
;; Итерация по списку
(dolist (item my-list)
(format t "~a " item))
;; Цикл с условием
(loop for i from 1 to 5
do (format t "~a " i)) ;; Выведет: 1 2 3 4 5
7. Ввод-вывод
;; Простой вывод
(print "Hello world!")
;; Форматированный вывод (аналог printf)
(format t "Hello, ~a! You have ~d messages." "Alice" 5)
;; Чтение с клавиатуры
(setf user-input (read-line))
Основные диалекты Lisp: Emacs Lisp, AutoLISP и Common Lisp
На протяжении долгой истории Lisp появилось множество его диалектов, каждый из которых был создан для решения определенных задач.
- Common Lisp (CL): Стандартизированный язык-преемник, объединивший большинство возможностей. Является мощным языком общего назначения. Яркие примеры ПО на CL: редактор Grammarly, серверная часть Reddit на ранних этапах.
- Emacs Lisp (Elisp): Это сердце одного из самых популярных текстовых редакторов в мире — GNU Emacs. Практически вся бесконечная настраиваемость редактора реализована именно на нем.
- AutoLISP: Специализированный диалект, встроенный в систему автоматизированного проектирования AutoCAD. Десятки тысяч инженеров по всему миру используют его для автоматизации рутинных задач черчения.
Лисп в СССР
Советские учёные также внесли вклад в развитие Lisp. Задача была не просто портировать, а создать полноценную систему на отечественной элементной базе:
БЭСМ-6 (1960-е): С.С. Лавров и Г.С. Силагадзе разработали для этой мощной супер-ЭВМ интерпретатор, а затем и компилятор Lisp.
Новосибирская версия: Под руководством А.П. Ершова была создана Lisp-система с уникальной чертой — русифицированной версией. Она использовалась в пионерских исследованиях по верификации программ и поддержке процесса разработки ПО.
Компьютеры ДВК и УКНЦ, работавшие на советских клонах PDP-11, имели на борту реализации Lisp, которые использовались в системах ИИ и для обучения. А легендарная советская супер-ЭВМ БЭСМ-6 стала одной из первых платформ, на которых в СССР начали осваивать Lisp.
Заключение
Причина, по которой Lisp до сих пор вдохновляет программистов, — его элегантность и адаптируемость. Программа на Lisp — это, по сути, структура данных. Это свойство позволяет использовать макросы, которые выходят далеко за рамки обычных подстановок кода. Макросы в Lisp буквально «переписывают» язык, превращая его в то, что нужно программисту прямо сейчас.
Lisp — это больше, чем язык; это живая история информатики. От своих теоретических основ до практических реализаций в AutoCAD и Emacs, он прошел путь, полный инноваций. Понимание идей, заложенных в Lisp, делает программиста лучше, открывая новые горизонты мышления, независимо от того, на каком языке он пишет сегодня.