What Made Lisp Different

Оригинал Перевод

Декабрь 2001 (обновлено в мае 2002)

(Эта статья появилась в ответ на некоторые вопросы в списке рассылки LL1. Теперь она включена в статью Revenge of the Nerds).

Когда Маккарти разработал Lisp в конце 1950-х, он радикально отличался от существующих языков, самым главным из которых был Fortran.

Lisp воплотил девять новых идей:


1. Условные высказывания. Условные высказывания это if-then-else конструкция. Сейчас мы воспринимаем их как должное. Они были изобретены Маккарти во время разработки Lisp. (Fortran в то время имел только goto-утверждения, тесно связанные с инструкцией ветвления на лежащем в основе железе.) Маккарти, будучи в комитете по Algol, внёс условные высказывания в Algol, откуда они распространились на другие языки.

2. Функциональные типы. В Lisp'е функции это объекты первого класса — они являются типом данных, также как числа, строки и т.д., и имеют буквальное представление, могут храниться в переменных, могут быть переданы как аргументы, и.т.д.

3. Рекурсия. Рекурсия, конечно, существовала как математическая концепция до Lisp'а, но Lisp был первым языком программирования поддерживающим её. (Это возможно подразумевается в создании функций как объектов первого класса.)

4. Новая концепция переменных. В Lisp'е все переменные являются эффективными указателями. Значения — это то, что есть у типов, а не у переменных, а присвоение или связывание переменных означает копирование указателей, а не того, на что они указывают.

5. Сборка мусора.

6. Программы состоят из выражений. Программы на Lisp'е это деревья выражений, каждое из которых возвращает значение. (Некоторые Lisp-выражения могут возвращать множественные значения.) Это входит в контраст с Fortran'ом и с множеством других успешных языков, которые различают «выражения» и «утверждения».

Было естественным иметь такое различие в Fortran'е, потому что язык был линейно-ориентированным (не удивительно для языка, в котором форматом ввода была перфокарта). Вы не могли иметь вложенные утверждения. И пока вам требовались математические выражения для работы, не было смысла в том, чтобы заставлять что-нибудь ещё возвращать значение, потому что могло не быть чего-то, что ожидало возврата.

Ограничения были сняты с появлением блочно-структурированных языков, но к тому моменту было уже слишком поздно. Различие между выражениями и утверждениями уже закрепилось. Оно перешло от Fortran'а к Algol'у и далее к их потомкам.

Когда язык сделан полностью из выражений, вы можете составлять выражения как пожелаете. Вы можете написать либо (используя синтаксис Arc)

либо

7. Символьный тип. Символы отличаются от строк, в этом случае вы можете проверить на равенство, сравнив указатели.

8. Нотация для кода с использованием деревьев из символов.

9. Весь язык всегда доступен. Нет явного различия между временем чтения, временем компиляции и временем выполнения. Вы можете компилировать или запускать код во время чтения, или читать или запускать кода пока компилируете, или читать или компилировать код во время выполнения.

Запуск кода во время чтения позволяет пользователям перепрограммировать синтаксис Lisp'а; запуск кода во время компиляции это основа для макросов; компилирование во время выполнения это основа использования Lisp'ов как языка расширения в таких программах как Emacs; и наконец, чтение во время выполнения позволяет программам взаимодействовать, используя s-выражения, идея, недавно переизобретённая в XML.


Когда Lisp был только изобретён, все эти идеи были сильно далеки от обычных практик программирования, которые диктовались железом, доступным в конце 1950-х.

Со временем язык по умолчанию, воплощённый в успехе популярных языков, постепенно эволюционировал в сторону Lisp. Пункты 1-5 теперь широко распространены. Пункт 6 начинает появляться в мэйнстриме. В Python'е в некотором виде есть пункт 7, хотя подходящего синтаксиса нет. Пункт 8, который (с пунктом 9) делает возможным макросы в Lisp'е, до сих пор есть только в Lisp'е, возможно потому что (а) он требует эти скобки или чего-то столь же плохого, и (б) если вы добавите это последнее увеличение мощности, то больше не сможете утверждать, что изобрели новый язык, а только лишь разработали новый диалект Lisp'а; -)

Хотя это полезно для современных программистов, странно описывать Lisp с точки зрения его отличия от случайных приёмов, принятых в других языках. Возможно это не то, о чём думал Маккарти. Lisp не был спроектирован, чтобы исправить ошибки Fortran'а; он появился скорее как побочный продукт попытки аксиоматизировать вычисления.