Лисп (язык программирования)
Парадигма | Мультипарадигма : функциональная , процедурная , рефлексивная , мета. |
---|---|
Разработано | Джон Маккарти |
Разработчик | Стив Рассел , Тимоти П. Харт, Майк Левин |
Впервые появился | 1960 год |
Дисциплина набора текста | Динамичный , сильный |
Диалекты | |
Под влиянием | |
Язык обработки информации (IPL) | |
Под влиянием | |
Лисп (исторически LISP , аббревиатура от «обработка списков») — это семейство языков программирования с долгой историей и характерной, полностью заключенной в круглые скобки префиксной нотацией . [3] Первоначально созданный в конце 1950-х годов, это второй по возрасту язык программирования высокого уровня, до сих пор широко используемый, после Фортрана . [4] [5] Лисп изменился с первых дней своего существования, и множество диалектов на протяжении его истории существовало . Сегодня наиболее известными диалектами Lisp общего назначения являются Common Lisp , Scheme , Racket и Clojure . [6] [7] [8]
Первоначально Лисп был создан как практическая математическая система обозначений для компьютерных программ под влиянием (но изначально не производного от) [9] обозначение Алонсо Чёрча лямбда-исчисления . Он быстро стал излюбленным языком программирования для исследований искусственного интеллекта (ИИ). [10] Как один из самых ранних языков программирования, Лисп стал пионером многих идей в информатике , включая древовидные структуры данных , автоматическое управление хранилищем , динамическую типизацию , условные выражения , функции высшего порядка , рекурсию , автономный компилятор . [11] и цикл чтения-оценки-печати . [12]
Название LISP происходит от «LISt Processor». [13] Связанные списки Lisp — одна из основных структур данных , а исходный код Lisp состоит из списков. Таким образом, программы на Лиспе могут манипулировать исходным кодом как структурой данных, создавая макросистемы , которые позволяют программистам создавать новый синтаксис или новые предметно-ориентированные языки, встроенные в Лисп.
Взаимозаменяемость кода и данных придает Lisp мгновенно узнаваемый синтаксис. Весь программный код записывается в виде s-выражений или списков в круглых скобках. Вызов функции или синтаксическая форма записывается в виде списка, в котором сначала имя функции или оператора, а затем аргументы; например, функция f
который принимает три аргумента, будет называться как (f arg1 arg2 arg3)
.
История
[ редактировать ]Джон Маккарти начал разработку Lisp в 1958 году, когда работал в Массачусетском технологическом институте (MIT). Маккарти опубликовал свой дизайн в статье в журнале Communications of ACM в апреле 1960 года под названием «Рекурсивные функции символических выражений и их машинное вычисление, часть I». [14] Он показал, что с помощью нескольких простых операторов и обозначений анонимных функций, заимствованных у Чёрча, можно построить полный по Тьюрингу язык алгоритмов.
Язык обработки информации был первым языком искусственного интеллекта , появившимся в 1955 или 1956 году, и уже включал в себя многие концепции, такие как обработка списков и рекурсия, которые стали использоваться в Лиспе.
В исходной записи Маккарти использовались « М-выражения », заключенные в квадратные скобки, которые переводились в S-выражения . Например, М-выражение car[cons[A,B]]
эквивалентно S-выражению (car (cons A B))
. Как только Lisp был реализован, программисты быстро решили использовать S-выражения, и от M-выражений отказались. М-выражения снова всплыли на поверхность благодаря недолгим попыткам MLisp [15] Горация Энеа и CGOL Воана Пратта .
Lisp был впервые реализован Стивом Расселом на компьютере IBM 704 с использованием перфокарт . [16] Рассел прочитал статью Маккарти и понял (к удивлению Маккарти), что функция eval в Лиспе может быть реализована в машинном коде .
По мнению Маккарти [17]
Стив Рассел сказал, смотри, почему бы мне не запрограммировать этот eval ... и я ему сказал: хо-хо, ты путаешь теорию с практикой, этот eval предназначен для чтения, а не для вычислений. Но он пошел дальше и сделал это. То есть он скомпилировал eval . из моей статьи в IBM 704 машинный код , исправив ошибки , а затем рекламировал это как интерпретатор Лиспа, что, безусловно, и было Итак, на тот момент Лисп по сути имел ту форму, которую он имеет сегодня...
Результатом стал работающий интерпретатор Лиспа , который можно было использовать для запуска программ на Лиспе или, точнее, «оценки выражений Лиспа».
Два макроса языка ассемблера для IBM 704 стали примитивными операциями для декомпозиции списков: car ( Содержимое адресной части номера регистра) и cdr ( Содержимое декрементной части номера регистра), [18] где «регистр» относится к регистрам (ЦП) компьютера центрального процессора . Диалекты Lisp до сих пор используют car
и cdr
( / k ɑːr / и / ˈ k ʊ d ər / ) для операций, которые возвращают первый элемент в списке и остальную часть списка соответственно.
Первый полный компилятор Лиспа, написанный на Лиспе, был реализован в 1962 году Тимом Хартом и Майком Левином в Массачусетском технологическом институте . -кратное увеличение скорости по сравнению со скоростью переводчика. [19] Этот компилятор представил модель инкрементной компиляции Lisp , в которой скомпилированные и интерпретируемые функции могут свободно смешиваться. Язык, использованный в записке Харта и Левина, гораздо ближе к современному стилю Лиспа, чем более ранний код Маккарти.
Правила сбора мусора были разработаны аспирантом Массачусетского технологического института Дэниелом Эдвардсом еще до 1962 года. [20]
В течение 1980-х и 1990-х годов были предприняты большие усилия по объединению работы над новыми диалектами Lisp (в основном преемниками Maclisp, такими как ZetaLisp и NIL (новая реализация Lisp) в один язык. Новый язык, Common Lisp , был в некоторой степени совместим. с диалектами, которые он заменил (в книге Common Lisp the Language отмечается совместимость различных конструкций). В 1994 году ANSI опубликовал стандарт Common Lisp «ANSI X3.226-1994 Язык программирования информационных технологий Common Lisp».
Хронология
[ редактировать ]1958 | 1960 | 1965 | 1970 | 1975 | 1980 | 1985 | 1990 | 1995 | 2000 | 2005 | 2010 | 2015 | 2020 | ||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
ЛИСП 1, 1.5, ЛИСП 2 (заброшенный) | |||||||||||||||
Маклисп | |||||||||||||||
Интерлисп | |||||||||||||||
леев | |||||||||||||||
Лисп-машина Лисп | |||||||||||||||
Схема | Р5РС | Р6РС | R7RS маленький | ||||||||||||
НОЛЬ | |||||||||||||||
ЗИЛ (язык реализации Zork) | |||||||||||||||
Франц Лисп | |||||||||||||||
Общий Лисп | стандарт ANSI | ||||||||||||||
Лисп | |||||||||||||||
СО схемой | |||||||||||||||
XLISP | |||||||||||||||
Т | |||||||||||||||
На схеме | |||||||||||||||
Эмакс Лисп | |||||||||||||||
АвтоЛИСП | |||||||||||||||
ПикоЛисп | |||||||||||||||
Гамбит | |||||||||||||||
EuLisp | |||||||||||||||
ИСЛИСП | |||||||||||||||
ОпенЛисп | |||||||||||||||
Схема PLT | Ракетка | ||||||||||||||
новыйLISP | |||||||||||||||
GNU Коварство | |||||||||||||||
Визуальный ЛИСП | |||||||||||||||
Кложур | |||||||||||||||
Дуга | |||||||||||||||
ЛФЭ | |||||||||||||||
Он | |||||||||||||||
Хиалисп |
Подключение к искусственному интеллекту
[ редактировать ]С момента своего создания Lisp был тесно связан с исследовательским сообществом в области искусственного интеллекта , особенно в отношении PDP-10. [21] системы. Lisp использовался как реализация языка Micro Planner , который использовался в знаменитой системе искусственного интеллекта SHRDLU . В 1970-х годах, когда исследования искусственного интеллекта породили коммерческие ответвления, производительность существующих систем Lisp стала растущей проблемой, поскольку программистам необходимо было знать влияние на производительность различных методов и вариантов реализации Lisp. [22]
Генеалогия и варианты
[ редактировать ]За свою шестидесятилетнюю историю Лисп породил множество вариаций основной темы языка S-выражений. Более того, каждый данный диалект может иметь несколько реализаций — например, существует более десятка реализаций Common Lisp .
Различия между диалектами могут быть весьма заметными — например, Common Lisp использует ключевое слово defun
чтобы назвать функцию, но Scheme использует define
. [23] Однако в рамках стандартизированного диалекта соответствующие реализации поддерживают один и тот же базовый язык, но с разными расширениями и библиотеками.
Исторически значимые диалекты
[ редактировать ]- ЛИСП 1 [24] – Первая реализация.
- ЛИСП 1.5 [25] – Первая широко распространенная версия, разработанная Маккарти и другими сотрудниками Массачусетского технологического института. Назван так потому, что он содержал несколько улучшений по сравнению с исходным интерпретатором «LISP 1», но не представлял собой серьезной реструктуризации, как запланированный LISP 2 .
- Стэнфордский ЛИСП 1.6 [26] – Преемник LISP 1.5, разработанный в Стэнфордской лаборатории искусственного интеллекта и широко распространяемый в PDP-10 системах , работающих под управлением операционной системы TOPS-10 . Maclisp и InterLisp сделали его устаревшим.
- Маклисп [27] MIT – MACLISP, разработанный для проекта MAC , является прямым потомком LISP 1.5. Он работал на системах PDP-10 и Multics . MACLISP позже стал называться Maclisp и часто упоминается как MacLisp. «MAC» в MACLISP не имеет отношения к Apple Macintosh или McCarthy .
- Интерлисп [28] — разработан в BBN Technologies для систем PDP-10 под управлением операционной системы TENEX , позже принят как Lisp «Западного побережья» для машин Xerox Lisp как InterLisp-D . Небольшая версия под названием «InterLISP 65» была опубликована для MOS Technology 6502 на базе 8-битных компьютеров Atari . Maclisp и InterLisp были сильными конкурентами.
- Франц Лисп – первоначально Калифорнийского университета в Беркли проект ; позже разработано компанией Franz Inc. Название представляет собой юмористическую деформацию имени « Франц Лист » и не относится к Allegro Common Lisp , диалекту Common Lisp, продаваемому компанией Franz Inc. в последние годы.
- XLISP , AutoLISP . на котором основан
- Standard Lisp и Portable Standard Lisp широко использовались и портировались, особенно вместе с системой компьютерной алгебры REDUCE.
- ZetaLisp , также называемый Lisp Machine Lisp — используется на машинах Lisp , прямой потомок Maclisp. ZetaLisp оказал большое влияние на Common Lisp.
- LeLisp — диалект французского Лиспа. Один из первых разработчиков интерфейсов (так называемый SOS Interface). [29] ) был написан на LeLisp.
- Схема (1975). [30]
- Common Lisp (1984), как описано в Common Lisp the Language — объединение нескольких разошедшихся попыток (ZetaLisp, Spice Lisp , NIL и S-1 Lisp ) по созданию диалектов-преемников. [31] до Maclisp, с существенным влиянием диалекта Scheme. Эта версия Common Lisp была доступна для самых разных платформ и была принята многими как стандарт де-факто. [32] до публикации ANSI Common Lisp (ANSI X3.226-1994). Среди наиболее распространенных поддиалектов Common Lisp — Steel Bank Common Lisp (SBCL), CMU Common Lisp (CMU-CL), Clozure OpenMCL (не путать с Clojure!), GNU CLisp и более поздние версии Franz Lisp; все они соответствуют более позднему стандарту ANSI CL (см. ниже).
- В своей первой версии Dylan представлял собой смесь Scheme и объектной системы Common Lisp.
- EuLisp — попытка разработать новый эффективный и очищенный Lisp.
- ISLISP – попытка разработать новый эффективный и понятный Lisp. Стандартизировано как ISO/IEC 13816:1997. [33] и позже пересмотренный как ISO/IEC 13816:2007: [34] Информационные технологии – Языки программирования, их среды и интерфейсы системного программного обеспечения – Язык программирования ISLISP .
- IEEE Схема – стандарт IEEE, 1178–1990 (R1995).
- ANSI Common Lisp — Американского национального института стандартов (ANSI) стандарт для Common Lisp, созданный подкомитетом X3J13 , зарегистрированный [35] начать с Common Lisp: The Language как базового документа и проработать процесс общественного консенсуса для поиска решений общих проблем переносимости программ и совместимости реализаций Common Lisp. Хотя формально это стандарт ANSI, реализация, продажа, использование и влияние ANSI Common Lisp наблюдались и продолжают наблюдаться во всем мире.
- ACL2 или «Вычислительная логика для аппликативного Common Lisp», аппликативный (без побочных эффектов) вариант Common LISP. ACL2 — это одновременно язык программирования, который может моделировать компьютерные системы, и инструмент, помогающий доказать свойства этих моделей.
- Clojure , новый диалект Lisp, который компилируется в виртуальную машину Java и уделяет особое внимание параллелизму .
- Game Oriented Assembly Lisp (или GOAL) — язык программирования видеоигр, разработанный Энди Гэвином из Naughty Dog . Он был написан с использованием Allegro Common Lisp и использовался при разработке всей серии игр Jak and Daxter, разработанной Naughty Dog.
2000 по настоящее время
[ редактировать ]После некоторого снижения в 1990-х годах интерес к Лиспу возобновился после 2000 года. Большая часть новой деятельности была сосредоточена вокруг реализаций Common Lisp , Scheme , Emacs Lisp , Clojure и Racket , а также включала разработку новых переносимых библиотек и приложений.
Многие новые программисты на Лиспе были вдохновлены такими авторами, как Пол Грэм и Эрик С. Рэймонд, на разработку языка, который другие считали устаревшим. Программисты New Lisp часто описывают этот язык как поучительный опыт и утверждают, что он значительно более продуктивен, чем другие языки. [36] Этот рост осведомленности можно противопоставить « зиме искусственного интеллекта » и кратковременному успеху Лиспа в середине 1990-х годов. [37]
По состоянию на 2010 год [update], существовало одиннадцать активно поддерживаемых реализаций Common Lisp. [38]
Сообщество открытого исходного кода создало новую вспомогательную инфраструктуру: CLiki — это вики, которая собирает информацию, связанную с Common Lisp, в каталоге Common Lisp перечислены ресурсы, #lisp — популярный IRC-канал, позволяющий делиться и комментировать фрагменты кода (с поддержкой lispaste , IRC -бот, написанный на Lisp), Planet Lisp [39] собирает содержимое различных блогов, посвященных Lisp, на LispForum. [40] пользователи обсуждают темы Lisp, Lispjobs [41] — это сервис для объявления предложений о работе, а также существует еженедельная служба новостей Weekly Lisp News . Common-lisp.net — это хостинг для проектов Common Lisp с открытым исходным кодом. Квиклисп [42] является менеджером библиотеки Common Lisp.
Пятьдесят лет Лиспа (1958–2008) отмечали на LISP50@OOPSLA. [43] Регулярно проводятся встречи местных пользователей в Бостоне, Ванкувере и Гамбурге. Другие мероприятия включают Европейское собрание Common Lisp, Европейский симпозиум Lisp и Международную конференцию Lisp.
Сообщество Scheme активно поддерживает более двадцати реализаций . Несколько важных новых реализаций (Chicken, Gambit, Gauche, Ikarus, Larceny, Ypsilon) были разработаны в 2000-х (десятилетии). Пересмотренный 5 Отчет об алгоритмической языковой схеме [44] Стандарт Scheme получил широкое признание в сообществе Scheme. было В ходе процесса запросов на реализацию схемы создано множество квазистандартных библиотек и расширений для схемы. Сообщества пользователей отдельных реализаций Scheme продолжают расти. Новый процесс стандартизации языка был начат в 2003 году и привел к появлению R 6 Стандарт RS Scheme в 2007 году. Академическое использование Scheme для преподавания информатики, похоже, несколько сократилось. Некоторые университеты больше не используют Scheme на вводных курсах по информатике; [45] [46] MIT теперь использует Python вместо Scheme в своей программе бакалавриата по информатике и в массовом открытом онлайн-курсе MITx. [47] [48]
Появилось несколько новых диалектов Lisp: Arc , Hy , Nu , Liskell и LFE (Lisp Flavored Erlang). Парсер Julia реализован на Femtolisp, диалекте Scheme (Julia вдохновлена Scheme, который, в свою очередь, является диалектом Lisp).
В октябре 2019 года Пол Грэм опубликовал спецификацию Bel , «нового диалекта Lisp».
Основные диалекты
[ редактировать ]Common Lisp и Scheme представляют собой два основных направления разработки Lisp. Эти языки воплощают существенно разные варианты дизайна.
Common Lisp является преемником Maclisp . Основное влияние оказали Lisp Machine Lisp , Maclisp, NIL , S-1 Lisp , Spice Lisp и Scheme. [49] Он обладает многими функциями Lisp Machine Lisp (большого диалекта Lisp, используемого для программирования Lisp Machines ), но был разработан для эффективной реализации на любом персональном компьютере или рабочей станции. Common Lisp — это язык программирования общего назначения, поэтому он имеет большой языковой стандарт, включающий множество встроенных типов данных, функций, макросов и других элементов языка, а также объектную систему ( Common Lisp Object System ). Common Lisp также позаимствовал некоторые функции из Scheme, такие как лексическая область видимости и лексические замыкания . Доступны общие реализации Lisp для различных платформ, таких как LLVM , [50] виртуальная машина Java , [51] x86-64, PowerPC, Alpha, ARM, Motorola 68000 и MIPS, [52] и операционные системы, такие как Windows, macOS, Linux, Solaris, FreeBSD, NetBSD, OpenBSD, Dragonfly BSD и Heroku. [53]
Scheme — это статически ограниченный и правильно рекурсивный диалект языка программирования Lisp, изобретенный Гаем Л. Стилом-младшим и Джеральдом Джеем Сассманом . Он был разработан, чтобы иметь исключительно ясную и простую семантику и несколько различных способов формирования выражений. Разработанный примерно на десять лет раньше, чем Common Lisp, Scheme имеет более минималистичный дизайн. Он имеет гораздо меньший набор стандартных функций, но с некоторыми функциями реализации (такими как оптимизация хвостовых вызовов и полные продолжения ), не указанными в Common Lisp. Широкий спектр парадигм программирования, включая императивные, функциональные стили и стили передачи сообщений, находят удобное выражение в Scheme. Схема продолжает развиваться с появлением ряда стандартов (пересмотренных н Отчет об алгоритмической языковой схеме) и серию Запросов на реализацию схемы .
Clojure — это диалект Lisp, ориентированный в основном на виртуальную машину Java , среду Common Language Runtime (CLR), виртуальную машину Python , виртуальную машину Ruby YARV и компиляцию в JavaScript . Он спроектирован как прагматичный язык общего назначения. Clojure черпает значительное влияние из Haskell и уделяет очень большое внимание неизменяемости. [54] Clojure предоставляет доступ к платформам и библиотекам Java с дополнительными подсказками типов и выводом типов , так что вызовы Java могут избежать отражения и обеспечить быстрые примитивные операции. Clojure не предназначен для обратной совместимости с другими диалектами Lisp. [55]
Кроме того, диалекты Lisp используются в качестве языков сценариев во многих приложениях, наиболее известными из которых являются Emacs Lisp в редакторе Emacs , AutoLISP и более поздний Visual Lisp в AutoCAD , Nyquist в Audacity и Scheme в LilyPond . Потенциально небольшой размер полезного интерпретатора Scheme делает его особенно популярным для встроенных сценариев. Примеры включают SIOD и TinyScheme , оба из которых были успешно встроены в процессор изображений GIMP под общим названием «Script-fu». [56] LIBREP, интерпретатор Lisp, разработанный Джоном Харпером, первоначально основанный на языке Emacs Lisp , был встроен в Sawfish оконный менеджер . [57]
Стандартизированные диалекты
[ редактировать ]В Lisp есть официально стандартизированные диалекты: R6RS Scheme , R7RS Scheme , IEEE Scheme, [58] ANSI Common Lisp и ISO ISLISP .
Языковые инновации
[ редактировать ]Пол Грэм выделяет девять важных аспектов Лиспа, которые отличают его от существующих языков, таких как Фортран : [59]
- Условные операторы, не ограничивающиеся переходом
- Первоклассные функции
- Рекурсия
- Единообразное обращение с переменными как с указателями , оставляя типы значениям.
- Сбор мусора
- Программы, полностью состоящие из выражений без операторов.
- Тип данных символа , отличный от строки . типа данных
- Обозначение кода, состоящего из деревьев символов (с использованием множества круглых скобок ).
- Полный язык доступен во время загрузки , во время компиляции и во время выполнения.
Лисп был первым языком, в котором структура программного кода точно и непосредственно представлена в стандартной структуре данных — качество, гораздо позже получившее название « гомоиконичность ». Таким образом, функциями Lisp можно манипулировать, изменять или даже создавать внутри программы Lisp без манипуляций на более низком уровне. Обычно это считается одним из основных преимуществ языка с точки зрения его выразительной силы и делает язык пригодным для синтаксических макросов и метациклических вычислений .
Условное выражение, использующее синтаксис if-then-else, было изобретено Маккарти для шахматной программы, написанной на Фортране . Он предложил включить его в АЛГОЛ , но он не стал частью спецификации Алгола 58 . Для Лиспа Маккарти использовал более общую структуру cond . [60] Алгол 60 взял на вооружение «если-то-иначе» и популяризировал его.
Лисп оказал глубокое влияние на Алана Кея , руководителя исследовательской группы, разработавшей Smalltalk в Xerox PARC ; и, в свою очередь, на Лисп повлиял Smalltalk, а более поздние диалекты в 1970-х годах переняли функции объектно-ориентированного программирования (классы наследования, инкапсуляция экземпляров, передача сообщений и т. д.). Объектная система Flavors представила концепцию множественного наследования и примеси . Объектная система Common Lisp обеспечивает множественное наследование, мультиметоды с множественной диспетчеризацией и первоклассные универсальные функции , создавая гибкую и мощную форму динамической диспетчеризации . Он послужил шаблоном для многих последующих объектных систем Lisp (включая Scheme ), которые часто реализовывались через метаобъектный протокол — рефлексивный метациклический дизайн , в котором объектная система определяется с точки зрения самой себя: Lisp был лишь вторым языком. после Smalltalk (и до сих пор это один из немногих языков), обладающих такой метаобъектной системой. Много лет спустя Алан Кей предположил, что в результате слияния этих функций только Smalltalk и Lisp можно считать правильно продуманными системами объектно-ориентированного программирования. [61]
Лисп представил концепцию автоматической сборки мусора , при которой система ходит по куче в поисках неиспользуемой памяти. Прогресс в разработке современных сложных алгоритмов сборки мусора, таких как сборка мусора по поколениям, был стимулирован их использованием в Lisp. [62]
Эдсгер В. Дейкстра в своей лекции на Премии Тьюринга 1972 года сказал:
Имея в своей основе несколько базовых принципов, он [LISP] продемонстрировал замечательную стабильность. Кроме того, LISP стал основой для значительного числа наших самых сложных компьютерных приложений. LISP в шутку называют «самым умным способом неправильного использования компьютера». Я думаю, что это описание — великий комплимент, поскольку оно передает всю суть освобождения: оно помогло ряду наших самых одаренных собратьев задуматься о ранее невозможных мыслях. [63]
Во многом из-за своих требований к ресурсам раннего вычислительного оборудования (включая ранние микропроцессоры), Лисп не стал таким популярным за пределами сообщества искусственного интеллекта , как Фортран и АЛГОЛА , потомок язык C . Из-за своей пригодности для сложных и динамичных приложений в 2010-х годах к Лиспу вновь возродился общественный интерес. [64]
Синтаксис и семантика
[ редактировать ]- Примеры в этой статье написаны на Common Lisp (хотя большинство из них также подходят и для Scheme ).
Символические выражения (S-выражения)
[ редактировать ]Лисп — язык, ориентированный на выражения . не делается различий В отличие от большинства других языков, между «выражениями» и «утверждениями» ; [ сомнительно – обсудить ] весь код и данные записываются в виде выражений. Когда выражение оценивается , оно создает значение (возможно, несколько значений), которое затем можно внедрить в другие выражения. Каждое значение может быть любым типом данных.
В статье Маккарти 1958 года были представлены два типа синтаксиса: символические выражения ( S-выражения , sexps), которые отражают внутреннее представление кода и данных; и метавыражения ( М-выражения ), которые выражают функции S-выражений. М-выражения никогда не пользовались популярностью, и сегодня почти все Lisps используют S-выражения для манипулирования как кодом, так и данными.
Использование круглых скобок — самое очевидное отличие Лиспа от других семейств языков программирования. В результате студенты уже давно дали Лиспу прозвища, такие как « Потерянные в глупых скобках » или «Множество раздражающих лишних скобок» . [65] Однако синтаксис S-выражений также отвечает за большую часть возможностей Лиспа: синтаксис прост и последователен, что облегчает манипулирование компьютером. Однако синтаксис Лиспа не ограничивается традиционной записью в круглых скобках. Его можно расширить, включив в него альтернативные обозначения. Например, XMLisp — это расширение Common Lisp, которое использует протокол метаобъектов для интеграции S-выражений с расширяемым языком разметки ( XML ).
Использование выражений придает языку большую гибкость. Поскольку функции Lisp записываются в виде списков, их можно обрабатывать точно так же, как и данные. Это позволяет легко писать программы, которые манипулируют другими программами ( метапрограммирование ). Многие диалекты Лиспа используют эту возможность с помощью макросистем, что позволяет расширять язык практически без ограничений.
Списки
[ редактировать ]Список Lisp записывается так, что его элементы разделяются пробелами и заключаются в круглые скобки. Например, (1 2 foo)
это список, элементами которого являются три атома 1
, 2
, и foo
. Эти значения типизированы неявно: они представляют собой соответственно два целых числа и тип данных, специфичный для Lisp, называемый «символ», и их не обязательно объявлять как таковые.
Пустой список ()
также представлен как особый атом nil
. Это единственная сущность в Лиспе, которая одновременно является атомом и списком.
Выражения записываются в виде списков с использованием префиксной записи . Первый элемент в списке — это имя функции, имя макроса, лямбда-выражение или имя «специального оператора» (см. ниже). Остальная часть списка — это аргументы. Например, функция list
возвращает свои аргументы в виде списка, поэтому выражение
(list 1 2 (quote foo))
оценивает список (1 2 foo)
. «Цитата» перед foo
в предыдущем примере — это «специальный оператор», который возвращает свой аргумент, не вычисляя его. Любые выражения, не заключенные в кавычки, рекурсивно вычисляются перед вычислением заключающего выражения. Например,
(list 1 2 (list 3 4))
оценивает список (1 2 (3 4))
. Третий аргумент — это список; списки могут быть вложенными.
Операторы
[ редактировать ]Аналогично обрабатываются арифметические операторы. Выражение
(+ 1 2 3 4)
оценивается как 10. Эквивалентом в инфиксной записи будет " 1 + 2 + 3 + 4
".
В Лиспе нет понятия операторов, реализованного в языках, производных от Алгола. Арифметические операторы в Лиспе — это вариативные функции (или n-арные ), способные принимать любое количество аргументов. Оператор приращения '++' в стиле C иногда реализуется под именем incf
давая синтаксис
(incf x)
эквивалентно (setq x (+ x 1))
, возвращая новое значение x
.
«Специальные операторы» (иногда называемые «специальными формами») обеспечивают структуру управления Лиспом. Например, специальный оператор if
принимает три аргумента. Если первый аргумент не равен нулю, он оценивается как второй аргумент; в противном случае он оценивается как третий аргумент. Таким образом, выражение
(if nil
(list 1 2 "foo")
(list 3 4 "bar"))
оценивается как (3 4 "bar")
. Конечно, это было бы полезнее, если бы вместо выражения было подставлено нетривиальное выражение. nil
.
В Lisp также предусмотрены логические операторы and , or и not . Операторы and и or выполняют сокращенную оценку и возвращают свой первый нулевой и ненулевой аргумент соответственно.
(or (and "zero" nil "never") "James" 'task 'time)
будет оцениваться как «Джеймс».
Лямбда-выражения и определение функции
[ редактировать ]Еще один специальный оператор, lambda
, используется для привязки переменных к значениям, которые затем оцениваются в выражении. Этот оператор также используется для создания функций: аргументы lambda
представляют собой список аргументов и выражение или выражения, которые вычисляет функция (возвращаемое значение — это значение последнего вычисляемого выражения). Выражение
(lambda (arg) (+ arg 1))
вычисляет функцию, которая при применении принимает один аргумент, привязывает его к arg
и возвращает число на единицу больше этого аргумента. Лямбда-выражения обрабатываются так же, как и именованные функции; они вызываются одинаково. Следовательно, выражение
((lambda (arg) (+ arg 1)) 5)
оценивается как 6
. Здесь мы делаем приложение функции: выполняем анонимную функцию , передавая ей значение 5.
Именованные функции создаются путем сохранения лямбда-выражения в символе с помощью макроса defun.
(defun foo (a b c d) (+ a b c d))
(defun f (a) b...)
определяет новую функцию с именем f
в глобальной среде. Концептуально оно похоже на выражение:
(setf (fdefinition 'f) #'(lambda (a) (block f b...)))
где setf
это макрос, используемый для установки значения первого аргумента fdefinition 'f
в новый функциональный объект. fdefinition
— это глобальное определение функции для функции с именем f
. #'
это аббревиатура от function
специальный оператор, возвращающий объект функции.
Атомы
[ редактировать ]В исходном LISP было два фундаментальных типа данных : атомы и списки. Список представлял собой конечную упорядоченную последовательность элементов, где каждый элемент был либо атомом, либо списком, а атом — числом или символом. Символ, по сути, представлял собой уникальный именованный элемент, записанный в виде буквенно-цифровой строки в исходном коде и используемый либо как имя переменной, либо как элемент данных при символьной обработке . Например, список (FOO (BAR 1) 2)
содержит три элемента: символ FOO
, список (BAR 1)
, и цифра 2.
Существенная разница между атомами и списками заключалась в том, что атомы были неизменяемыми и уникальными. Два атома, появившиеся в разных местах исходного кода, но написанные совершенно одинаково, представляли один и тот же объект. [ нужна ссылка ] тогда как каждый список представлял собой отдельный объект, который можно было изменять независимо от других списков и отличать его от других списков с помощью операторов сравнения.
По мере того как в более поздних диалектах Лиспа было введено больше типов данных и развивались стили программирования , концепция атома теряла значение. [ нужна ссылка ] предиката Во многих диалектах все еще сохранялся атом для совместимости с устаревшими версиями . [ нужна ссылка ] определение этого истинно для любого объекта, который не является минусом.
Минусы и списки
[ редактировать ]Список Lisp реализован как односвязный список . [66] Каждая ячейка этого списка называется cons (в Scheme — пара ) и состоит из двух указателей , называемых car и cdr . Они соответственно эквивалентны data
и next
статьи поля, обсуждаемые в связанном списке .
Из множества структур данных, которые можно построить из ячеек cons, одна из самых простых называется правильным списком . Правильный список — это либо специальный nil
(пустой список) или символ «минус», в котором car
указывает на данные (которые могут быть другой структурой cons, например списком), а cdr
указывает на другой правильный список.
Если данный cons считается главой связанного списка, то его car указывает на первый элемент списка, а его cdr указывает на остальную часть списка. По этой причине car
и cdr
функции еще называют first
и rest
когда речь идет о консах, которые являются частью связанного списка (а не, скажем, дерева).
Таким образом, список Lisp не является атомарным объектом, каким был бы экземпляр класса-контейнера в C++ или Java. Список — это не что иное, как совокупность связанных конусов. Переменная, которая ссылается на данный список, является просто указателем на первый минус в списке. Обход списка можно выполнить, вниз пропустив список ; то есть использование последовательных CDR для посещения каждого минуса в списке; или используя любую из нескольких функций более высокого порядка для сопоставления функции со списком.
Поскольку константы и списки настолько универсальны в системах Lisp, распространено заблуждение, что они являются единственными структурами данных Lisp. Фактически, все Лиспы, кроме самых упрощенных, имеют другие структуры данных, такие как векторы ( массивы ), хеш-таблицы , структуры и т. д.
S-выражения представляют списки
[ редактировать ]S-выражения в скобках представляют структуры связанного списка. Существует несколько способов представить один и тот же список в виде S-выражения. Минусы можно записать в виде пар точек с точками как (a . b)
, где a
это машина и b
cдр. Можно было бы написать более длинный список. (a . (b . (c . (d . nil))))
в обозначениях пар точек. Условно это сокращенно обозначается как (a b c d)
в обозначении списка . Неправильный список [67] может быть записано в комбинации двух – как (a b c . d)
для списка трех конусов, последний cdr которых d
(т.е. список (a . (b . (c . d)))
в полной форме).
Процедуры обработки списков
[ редактировать ]Lisp предоставляет множество встроенных процедур для доступа к спискам и управления ими. Списки можно создавать непосредственно с помощью list
процедура, которая принимает любое количество аргументов и возвращает список этих аргументов.
(list 1 2 'a 3)
;Output: (1 2 a 3)
(list 1 '(2 3) 4)
;Output: (1 (2 3) 4)
Из-за того, что списки составляются из пар минусов , cons
Процедура может использоваться для добавления элемента в начало списка. cons
Процедура асимметрична в том, как она обрабатывает аргументы списка, из-за того, как списки создаются.
(cons 1 '(2 3))
;Output: (1 2 3)
(cons '(1 2) '(3 4))
;Output: ((1 2) 3 4)
The append
Процедура добавляет два (или более) списка друг к другу. Поскольку списки Lisp являются связанными списками, добавление двух списков имеет асимптотическую временную сложность.
(append '(1 2) '(3 4))
;Output: (1 2 3 4)
(append '(1 2 3) '() '(a) '(5 6))
;Output: (1 2 3 a 5 6)
Общая структура
[ редактировать ]Списки Lisp, будучи простыми связанными списками, могут иметь общую структуру друг с другом. То есть два списка могут иметь один и тот же хвост или конечную последовательность выводов. Например, после выполнения следующего кода Common Lisp:
(setf foo (list 'a 'b 'c))
(setf bar (cons 'x (cdr foo)))
списки foo
и bar
являются (a b c)
и (x b c)
соответственно. Однако хвост (b c)
имеет одинаковую структуру в обоих списках. Это не копия; ячейки минусов, указывающие на b
и c
находятся в одних и тех же ячейках памяти для обоих списков.
Совместное использование структуры вместо копирования может привести к значительному повышению производительности. Однако этот метод может нежелательным образом взаимодействовать с функциями, которые изменяют списки, передаваемые им в качестве аргументов. Изменение одного списка, например, путем замены c
с goose
, повлияет на другое:
(setf (third foo) 'goose)
Это меняет foo
к (a b goose)
, но тем самым также изменяется bar
к (x b goose)
– возможно, неожиданный результат. Это может быть источником ошибок, и функции, изменяющие свои аргументы, документируются как деструктивные именно по этой причине .
Поклонники функционального программирования избегают деструктивных функций. В диалекте схемы, который отдает предпочтение функциональному стилю, имена деструктивных функций отмечаются предостерегающим восклицательным знаком или «взрывом», например: set-car!
(читай набор car bang ), который заменяет машину из минусов. В диалекте Common Lisp деструктивные функции являются обычным явлением; эквивалент set-car!
назван rplaca
за "заменить машину". Однако эту функцию редко можно увидеть, поскольку Common Lisp включает в себя специальную возможность: setf
, чтобы упростить определение и использование деструктивных функций. В Common Lisp часто используют функциональный стиль написания кода (без деструктивных вызовов) при создании прототипа, а затем добавление деструктивных вызовов в качестве оптимизации там, где это безопасно.
Формы самооценки и цитирование
[ редактировать ]Лисп оценивает выражения, которые вводит пользователь. Символы и списки оценивают какое-то другое (обычно более простое) выражение — например, символ возвращает значение переменной, которую он называет; (+ 2 3)
оценивается как 5
. Однако большинство других форм оценивают сами себя: если ввести 5
в Лисп, он возвращает 5
.
Любое выражение также можно пометить, чтобы предотвратить его оценку (что необходимо для символов и списков). В этом заключается роль quote
специальный оператор или его аббревиатура '
(одна кавычка). Например, обычно при вводе символа foo
, он возвращает значение соответствующей переменной (или ошибку, если такой переменной нет). Чтобы обратиться к буквальному символу, введите (quote foo)
или, обычно, 'foo
.
И Common Lisp, и Scheme также поддерживают оператор обратной кавычки (называемый в Scheme квазицитой ), вводимый с помощью `
характер ( серьезный акцент ). Это почти то же самое, что и простая кавычка, за исключением того, что она позволяет оценивать выражения и интерполировать их значения в список кавычек с запятой. ,
снять кавычки и запятую ,@
операторы сращивания . Если переменная snue
имеет значение (bar baz)
затем `(foo ,snue)
оценивается как (foo (bar baz))
, пока `(foo ,@snue)
оценивается как (foo bar baz)
. Обратная кавычка чаще всего используется при определении расширений макросов. [68] [69]
Самовычисляемые формы и формы в кавычках являются эквивалентом лисперов в Лиспе. Возможно изменение значений (изменяемых) литералов в программном коде. Например, если функция возвращает форму в кавычках, а код, вызывающий функцию, изменяет форму, это может изменить поведение функции при последующих вызовах.
(defun should-be-constant ()
'(one two three))
(let ((stuff (should-be-constant)))
(setf (third stuff) 'bizarre)) ; bad!
(should-be-constant) ; returns (one two bizarre)
Изменение формы в кавычках, как это, обычно считается плохим стилем и определяется ANSI Common Lisp как ошибочное (приводящее к «неопределённому» поведению в скомпилированных файлах, поскольку компилятор файлов может объединить похожие константы, поместить их в память, защищенную от записи, и и т. д.).
Формализация цитаты в Лиспе была отмечена Дугласом Хофштадтером (в Гёделе, Эшере, Бахе ) и другими как пример философской идеи самореференции .
Область применения и закрытие
[ редактировать ]Семейство Lisp разделяется по использованию динамической или статической (лексической) области видимости . Clojure, Common Lisp и Scheme по умолчанию используют статическую область видимости, тогда как newLISP , Picolisp и встроенные языки в Emacs и AutoCAD используют динамическую область видимости. Начиная с версии 24.1, Emacs использует как динамическую, так и лексическую область видимости.
Списковая структура программного кода; эксплуатация макросами и компиляторами
[ редактировать ]Фундаментальное различие между Лиспом и другими языками заключается в том, что в Лиспе текстовое представление программы представляет собой просто удобочитаемое описание тех же внутренних структур данных (связных списков, символов, чисел, символов и т. д.), которые используются базовая система Lisp.
Лисп использует это для реализации очень мощной системы макросов. Как и другие макроязыки, например тот, который определяется препроцессором C (препроцессор макросов для языков программирования C , Objective-C и C++ ), макрос возвращает код, который затем можно скомпилировать. Однако, в отличие от макросов препроцессора C, макросы являются функциями Lisp и поэтому могут использовать всю мощь Lisp.
Кроме того, поскольку код Lisp имеет ту же структуру, что и списки, макросы можно создавать с помощью любой функции обработки списков в языке. Короче говоря, все, что Lisp может сделать со структурой данных, макросы Lisp могут сделать с кодом. Напротив, в большинстве других языков выходные данные синтаксического анализатора являются чисто внутренними по отношению к реализации языка и не могут манипулироваться программистом.
Эта функция позволяет легко разрабатывать эффективные языки внутри языков. Например, объектная система Common Lisp может быть реализована как расширение языка с использованием макросов. Это означает, что если приложению нужен другой механизм наследования, оно может использовать другую объектную систему. Это резко контрастирует с большинством других языков; например, Java не поддерживает множественное наследование, и нет разумного способа его добавить.
В упрощенных реализациях Lisp эта структура списка напрямую интерпретируется для запуска программы; функция — это буквально часть структуры списка, по которой интерпретатор проходит при ее выполнении. Однако большинство существенных систем Lisp также включают в себя компилятор. Компилятор преобразует структуру списка в машинный код или байт-код для выполнения. Этот код может работать так же быстро, как код, скомпилированный на обычных языках, таких как C.
Макросы расширяются перед этапом компиляции и, таким образом, предлагают некоторые интересные возможности. Если программе нужна предварительно вычисленная таблица, то макрос может создать таблицу во время компиляции, поэтому компилятору нужно только вывести таблицу и не вызывать код для создания таблицы во время выполнения. В некоторых реализациях Lisp даже есть механизм, eval-when
, что позволяет коду присутствовать во время компиляции (когда он понадобится макросу), но не присутствовать в создаваемом модуле. [70]
Оценка и цикл чтения-оценки-печати
[ редактировать ]Языки Lisp часто используются с интерактивной командной строкой , которую можно объединить с интегрированной средой разработки (IDE). Пользователь вводит выражения в командной строке или дает команду IDE передать их в систему Lisp. Лисп читает введенные выражения, оценивает их и печатает результат. По этой причине командная строка Lisp называется циклом чтения-оценки-печати ( REPL ).
Основная работа REPL заключается в следующем. Это упрощенное описание, в котором опущены многие элементы реального Лиспа, такие как кавычки и макросы.
The read
Функция принимает текстовые S-выражения в качестве входных данных и анализирует их во внутреннюю структуру данных. Например, если вы наберете текст (+ 1 2)
по подсказке, read
преобразует это в связанный список с тремя элементами: символом +
, число 1 и число 2. Так получилось, что этот список также является допустимым фрагментом кода Lisp; то есть его можно оценить. Это связано с тем, что машина списка называет функцию — операцию сложения.
А foo
будет читаться как один символ. 123
будет читаться как число сто двадцать три. "123"
будет читаться как строка «123».
The eval
функция оценивает данные, возвращая в результате ноль или более других данных Lisp. Оценка не обязательно должна означать интерпретацию; некоторые системы Lisp компилируют каждое выражение в собственный машинный код. Однако легко описать оценку как интерпретацию: чтобы оценить список, машина которого называет функцию, eval
сначала оценивает каждый из аргументов, указанных в его cdr, затем применяет функцию к аргументам. В данном случае функция складывает и применяет ее к списку аргументов. (1 2)
дает ответ 3
. Это результат оценки.
Символ foo
оценивается как значение символа foo. Такие данные, как строка «123», оцениваются как одна и та же строка. Список (quote (1 2 3))
возвращает список (1 2 3).
Это работа print
функция для представления вывода пользователю. Для простого результата, такого как 3
это тривиально. Выражение, которое оценивается как часть структуры списка, потребует, чтобы print
пройдите по списку и распечатайте его как S-выражение.
Чтобы реализовать Lisp REPL, необходимо реализовать только эти три функции и функцию бесконечного цикла. (Естественно, реализация eval
будет сложным, поскольку он также должен реализовывать все специальные операторы, такие как if
или lambda
.) После этого базовый REPL представляет собой одну строку кода: (loop (print (eval (read))))
.
Lisp REPL обычно также обеспечивает редактирование ввода, историю ввода, обработку ошибок и интерфейс для отладчика.
Lisp обычно оценивается с нетерпением . В Common Lisp аргументы оцениваются в аппликативном порядке («самый левый внутренний»), тогда как в Scheme порядок аргументов не определен, что оставляет место для оптимизации компилятором.
Структуры управления
[ редактировать ]Первоначально в Lisp было очень мало управляющих структур, но в ходе эволюции языка было добавлено гораздо больше. (Исходный условный оператор Лиспа, cond
, является предшественником более позднего if-then-else
структуры.)
Программисты, использующие диалект Scheme, часто выражают циклы, используя хвостовую рекурсию . Общность Scheme в академической информатике привела некоторых студентов к мысли, что хвостовая рекурсия — единственный или наиболее распространенный способ написания итераций в Lisp, но это неверно. Все часто встречающиеся диалекты Лиспа имеют конструкции итерации в императивном стиле, начиная с Scheme. do
цикл к Common Lisp комплексу loop
выражения. Более того, ключевой вопрос, который делает это объективным, а не субъективным вопросом, заключается в том, что Scheme предъявляет особые требования к обработке хвостовых вызовов , и, таким образом, причина, по которой использование хвостовой рекурсии обычно поощряется для Scheme, заключается в том, что эта практика явно поддерживается определение языка. Напротив, ANSI Common Lisp не требует [71] оптимизация, обычно называемая устранением хвостовых вызовов. Таким образом, тот факт, что стиль хвостовой рекурсии как случайная замена использованию более традиционных итерационных конструкций (таких как do
, dolist
или loop
) обескуражен [72] в Common Lisp это не просто вопрос стилистических предпочтений, но потенциально вопрос эффективности (поскольку очевидный хвостовой вызов в Common Lisp может не компилироваться как простой переход ) и корректности программы (поскольку хвостовая рекурсия может увеличить использование стека в Common Lisp, рискуя переполнение стека ).
Некоторые управляющие структуры Лиспа представляют собой специальные операторы , эквивалентные синтаксическим ключевым словам других языков. Выражения, использующие эти операторы, имеют тот же внешний вид, что и вызовы функций, но отличаются тем, что аргументы не обязательно оцениваются или, в случае выражения итерации, могут оцениваться более одного раза.
В отличие от большинства других основных языков программирования, Лисп позволяет реализовывать структуры управления с помощью языка. Некоторые структуры управления реализованы в виде макросов Lisp и даже могут быть расширены макросами программистом, который хочет знать, как они работают.
И Common Lisp, и Scheme имеют операторы для нелокального потока управления. Различия в этих операторах являются одними из самых глубоких различий между двумя диалектами. Схема поддерживает повторные продолжения с использованием call/cc
процедура, которая позволяет программе сохранить (а затем восстановить) определенное место выполнения. Common Lisp не поддерживает повторные продолжения, но поддерживает несколько способов обработки escape-продолжений.
Часто один и тот же алгоритм может быть выражен в Лиспе либо в императивном, либо в функциональном стиле. Как отмечалось выше, Scheme имеет тенденцию отдавать предпочтение функциональному стилю, используя хвостовую рекурсию и продолжения для выражения потока управления. Однако императивный стиль все же вполне возможен. Стиль, предпочитаемый многими программистами Common Lisp, может показаться более знакомым программистам, привыкшим к структурированным языкам, таким как C, тогда как стиль, предпочитаемый комбинаторами, больше напоминает чисто функциональные языки, такие как Haskell .
Благодаря раннему наследию Лиспа в области обработки списков, он имеет широкий набор функций высшего порядка, связанных с итерацией по последовательностям. Во многих случаях, когда в других языках необходим явный цикл (например, for
цикл в C) в Лиспе ту же задачу можно выполнить с помощью функции более высокого порядка. (То же самое относится и ко многим функциональным языкам программирования.)
Хорошим примером является функция, которая в Scheme называется map
и в Common Lisp называется mapcar
. Учитывая функцию и один или несколько списков, mapcar
последовательно применяет функцию к элементам списков по порядку, собирая результаты в новый список:
(mapcar #'+ '(1 2 3 4 5) '(10 20 30 40 50))
Это касается +
функцию для каждой соответствующей пары элементов списка, что дает результат (11 22 33 44 55)
.
Примеры
[ редактировать ]Вот примеры кода Common Lisp.
Базовая программа « Привет, Мир! »:
(print "Hello, World!")
Синтаксис Лиспа естественным образом поддается рекурсии. Математические проблемы, такие как перечисление рекурсивно определенных множеств, легко выразить в этих обозначениях. числа Например, чтобы вычислить факториал :
(defun factorial (n)
(if (zerop n) 1
(* n (factorial (1- n)))))
Альтернативная реализация занимает меньше места в стеке, чем предыдущая версия, если базовая система Lisp оптимизирует хвостовую рекурсию :
(defun factorial (n &optional (acc 1))
(if (zerop n) acc
(factorial (1- n) (* acc n))))
Сравните приведенные выше примеры с итеративной версией, использующей Common Lisp . loop
макрос:
(defun factorial (n)
(loop for i from 1 to n
for fac = 1 then (* fac i)
finally (return fac)))
Следующая функция переворачивает список. (Встроенная обратная функция Лиспа делает то же самое.)
(defun -reverse (list)
(let ((return-value))
(dolist (e list) (push e return-value))
return-value))
Объектные системы
[ редактировать ]Различные объектные системы и модели были построены поверх Lisp, вместе с ним или в него, в том числе
- Объектная система Common Lisp , CLOS, является неотъемлемой частью ANSI Common Lisp. CLOS произошел от New Flavors и CommonLOOPS. ANSI Common Lisp был первым стандартизированным объектно-ориентированным языком программирования (1994, ANSI X3J13).
- ОбъектЛисп [73] или Object Lisp , используемый Lisp Machines Incorporated и ранними версиями Macintosh Common Lisp.
- LOOPS (система объектно-ориентированного программирования Lisp) и более поздние версии CommonLoops
- Flavors , созданный в Массачусетском технологическом институте , и его потомок New Flavors (разработанный компанией Symbolics ).
- KR (сокращение от «Представление знаний») — объектная система на основе ограничений , разработанная для помощи в написании Garnet, библиотеки графического интерфейса для Common Lisp .
- Среда разработки знаний (KEE) использовала объектную систему UNITS и интегрировала ее с механизмом вывода. [74] и система поддержания истины (ATMS).
Операционные системы
[ редактировать ]Некоторые операционные системы , включая системы на основе языка , основаны на Lisp (используют функции Lisp, соглашения, методы, структуры данных и т. д.) или написаны на Lisp. [75] включая:
Genera , переименованная в Open Genera, [76] от Символики ; Medley, написанная на Interlisp, первоначально семействе графических операционных систем, работавших на Xerox более поздних Star рабочих станциях ; [77] [78] Сваха; [79] Промежуточный; [80] [81] КрисаЛисп, [82] от разработчиков TAOS компании Tao Systems. [83] , а также Штукатурка
См. также
[ редактировать ]Ссылки
[ редактировать ]- ^ "Введение" . Руководство Юлии . Прочтите Документы. Архивировано из оригинала 8 апреля 2016 г. Проверено 10 декабря 2016 г.
- ^ «Вопросы и ответы по языку Wolfram» . Вольфрам Исследования . Проверено 10 декабря 2016 г.
- ^ Эдвин Д. Рейли (2003). Вехи развития информатики и информационных технологий . Издательская группа Гринвуд. стр. 156–157. ISBN 978-1-57356-521-9 .
- ^ «СИКП: Предисловие» . Архивировано из оригинала 27 июля 2001 г.
Lisp выжил, его используют уже около четверти века. Среди активных языков программирования только Фортран просуществовал дольше.
- ^ «Выводы» . Архивировано из оригинала 3 апреля 2014 г. Проверено 4 июня 2014 г.
- ^ Стил, Гай Л. (1990). Common Lisp: язык (2-е изд.). Бедфорд, Массачусетс: Digital Press. ISBN 1-55558-041-6 . OCLC 20631879 .
- ^ Феллайзен, Матиас; Финдлер, Роберт; Флэтт, Мэтью; Кришнамурти, Шрирам; Верзеллий, Илий; Маккарти, Джей; Тобин-Хохштадт, Сэм (2015). « Манифест рэкета» ( PDF) .
- ^ «Clojure — Отличия от других Лиспов» . Clojure.org . Проверено 27 октября 2022 г.
- ^ Стил, Гай Льюис; Сассман, Джеральд Джей (май 1978 г.). «Искусство переводчика, или Комплекс модульности (Части нулевая, первая и вторая), Часть нулевая, ч. 4» . Библиотеки Массачусетского технологического института. hdl : 1721.1/6094 . Проверено 1 августа 2020 г.
- ^ Хофштадтер, Дуглас Р. (1999) [1979], Гёдель, Эшер, Бах: Вечная золотая коса (издание к двадцатой годовщине) , Basic Books, стр. 292, ISBN 0-465-02656-7 .
Одним из наиболее важных и увлекательных компьютерных языков является LISP (расшифровывается как «Обработка списков»), который был изобретен Джоном Маккарти примерно в то же время, когда был изобретен Алгол Впоследствии LISP пользовался большой популярностью среди специалистов по искусственному интеллекту.
- ^ Пол Грэм. «Месть ботанов» . Проверено 14 марта 2013 г.
- ^ Чисналл, Дэвид (12 января 2011 г.). Влиятельные языки программирования, часть 4: Лисп .
- ^ Джонс, Робин; Мейнард, Клайв; Стюарт, Ян (6 декабря 2012 г.). Искусство программирования на Лиспе . Springer Science & Business Media. п. 2. ISBN 9781447117193 .
- ^ Маккарти, Джон. «Рекурсивные функции символьных выражений и их машинное вычисление, часть I» . Архивировано из оригинала 4 октября 2013 г. Проверено 13 октября 2006 г.
- ^ Смит, Дэвид Кэнфилд. Руководство пользователя MLISP (PDF) . Проверено 13 октября 2006 г.
- ^ Маккарти, Джон (12 февраля 1979 г.). «История Лиспа: Лаборатория искусственного интеллекта» (PDF) .
- ^ Стоян, Герберт (6 августа 1984 г.). Ранняя история LISP (1956–1959) . LFP '84: Материалы симпозиума ACM 1984 года по LISP и функциональному программированию. Ассоциация вычислительной техники . п. 307. дои : 10.1145/800055.802047 .
- ^ Маккарти, Джон. «Предыстория LISP — лето 1956 г. — лето 1958 г.» . Проверено 14 марта 2010 г.
- ^ Харт, Тим; Левин, Майк. «AI Memo 39-Новый компилятор» (PDF) . Архивировано из оригинала (PDF) 13 декабря 2020 г. Проверено 18 марта 2019 г.
- ^ Маккарти, Джон; Абрахамс, Пол В.; Эдвардс, Дэниел Дж.; Харт, Тимоти П.; Левин, Майкл И. (1985) [1962]. Руководство программиста LISP 1.5 (PDF) . 15-е издание (2-е изд.). п. Предисловие.
- ^ На 36-битный размер слова PDP-6 / PDP-10 повлияла полезность наличия двух 18-битных указателей Lisp в одном слове. Питер Дж. Херли (18 октября 1990 г.). «История ТОПС или жизнь в быстрых АС» . Группа новостей : alt.folklore.computers . Usenet: [электронная почта защищена] .
Проект PDP-6 стартовал в начале 1963 года как 24-битная машина. Для LISP он вырос до 36 бит, что было целью разработки.
- ^ Стил, Гай Л.; Габриэль, Ричард П. (январь 1996 г.), Бергин, Томас Дж.; Гибсон, Ричард Г. (ред.), «Эволюция Лиспа» , История языков программирования ---II , Нью-Йорк, штат Нью-Йорк, США: ACM, стр. 233–330, doi : 10.1145/234286.1057818 , ISBN 978-0-201-89502-5 , получено 25 июля 2022 г.
- ^ Общий Лисп:
(defun f (x) x)
Схема:(define f (lambda (x) x))
или(define (f x) x)
- ^ Маккарти, Дж .; Брайтон, Р.; Эдвардс, Д.; Фокс, П .; Ходс, Л. ; Лакхэм, Д .; Малинг, К.; Парк, Д. ; Рассел, С. (март 1960 г.). Руководство программиста LISP I (PDF) . Бостон: Группа искусственного интеллекта, Вычислительный центр и исследовательская лаборатория Массачусетского технологического института. Архивировано из оригинала (PDF) 17 июля 2010 г. По состоянию на 11 мая 2010 г.
- ^ Маккарти, Джон; Абрахамс, Пол В.; Эдвардс, Дэниел Дж.; Харт, Тимоти П.; Левин, Майкл И. (1985) [1962]. Руководство программиста LISP 1.5 (PDF) (2-е изд.). МТИ Пресс . ISBN 0-262-13011-4 .
- ^ Куам, Линн Х.; Диффл, Уитфилд. Руководство по Стэнфордскому LISP 1.6 (PDF) .
- ^ «Справочное руководство по Maclisp» . 3 марта 1979 г. Архивировано из оригинала 14 декабря 2007 г.
- ^ Тейтельман, Уоррен (1974). Справочное руководство InterLisp (PDF) . Архивировано из оригинала (PDF) 2 июня 2006 г. Проверено 19 августа 2006 г.
- ^ Инструменты создания интерфейса: современное состояние и классификация Х. Эль Мрабета.
- ^ Джеральд Джей Сассман и Гай Льюис Стил-младший (декабрь 1975 г.). «Схема: интерпретатор расширенного лямбда-исчисления» (PDF) . Лаборатория искусственного интеллекта Массачусетского технологического института . АИМ-349 . Проверено 23 декабря 2021 г.
- ^ Стил, Гай Л. младший (1990). "Цель" . Common Lisp the Language (2-е изд.). Цифровая пресса. ISBN 0-13-152414-3 .
- ^ Кантровитц, Марк; Марголин, Барри (20 февраля 1996 г.). «История: откуда появился Лисп?» . FAQ: Часто задаваемые вопросы по Lisp 2/7 .
- ^ «ИСО/МЭК 13816:1997» . Исо.орг. 01.10.2007 . Проверено 15 ноября 2013 г.
- ^ «ИСО/МЭК 13816:2007» . Исо.орг. 30 октября 2013 г. Проверено 15 ноября 2013 г.
- ^ «Устав X3J13» .
- ^ «Опрос на пути к Lisp» . Архивировано из оригинала 4 октября 2006 г. Проверено 13 октября 2006 г.
- ^ «Тенденции будущего» . Faqs.org. Архивировано из оригинала 3 июня 2013 г. Проверено 15 ноября 2013 г.
- ^ Вайнреб, Дэниел. «Распространенные реализации Lisp: обзор» . Архивировано из оригинала 21 апреля 2012 г. Проверено 4 апреля 2012 г.
- ^ «Планета Лисп» . Проверено 12 октября 2023 г.
- ^ «ЛиспФорум» . Проверено 12 октября 2023 г.
- ^ «Лиспджобс» . Проверено 12 октября 2023 г.
- ^ «Квиклисп» . Проверено 12 октября 2023 г.
- ^ «LISP50@OOPSLA» . Lisp50.org . Проверено 15 ноября 2013 г.
- ^ Документы: Стандарты: R5RS . Schemers.org (11 января 2012 г.). Проверено 17 июля 2013 г.
- ^ «Почему MIT теперь использует Python вместо схемы для своей программы бакалавриата по информатике» . cemerick.com . 24 марта 2009 года. Архивировано из оригинала 17 сентября 2010 года . Проверено 10 ноября 2013 г.
- ^ Бродер, Эван (8 января 2008 г.). «Конец эпохи» . mitadmissions.org . Проверено 10 ноября 2013 г.
- ^ «Программы бакалавриата MIT EECS» . www.eecs.mit.edu . Массачусетский технологический институт электротехники и информатики . Проверено 31 декабря 2018 г.
- ^ «На вводный курс Python MITx записалось 1,2 миллиона человек» . MIT EECS . Массачусетский технологический институт электротехники и информатики . Проверено 31 декабря 2018 г.
- ^ Глава 1.1.2, История, стандарт ANSI CL
- ^ [1] Clasp — это реализация Common Lisp, которая взаимодействует с C++ и использует LLVM для JIT- компиляции в машинный код.
- ^ [2] «Armed Bear Common Lisp (ABCL) — это полная реализация языка Common Lisp, включающая как интерпретатор, так и компилятор, работающий в JVM»
- ^ [3] Архивировано 22 июня 2018 г. на сайте Wayback Machine Common Lisp Implements: опрос.
- ^ [4] Сравнение активно разрабатываемых реализаций Common Lisp.
- ^ Углубленный взгляд на коллекции Clojure , дата обращения 24 июня 2012 г.
- ^ «Кложур рациональный» . Проверено 27 августа 2019 г.
Clojure — это Lisp, не ограниченный обратной совместимостью.
- ^ Script-fu в GIMP 2.4 , дата обращения 29 октября 2009 г.
- ^ librep в Sawfish Wikia, получено 29 октября 2009 г.
- ^ «Схема IEEE» . IEEE 1178-1990 — Стандарт IEEE для языка программирования Scheme . Проверено 27 августа 2019 г.
- ^ Пол Грэм (май 2002 г.). «Что отличало Лисп» .
- ^ «Предыстория LISP — лето 1956 г. — лето 1958 г.» .
Я изобрел условные выражения в связи с набором правильных ходов в шахматах, которые я написал на ФОРТРАНЕ для IBM 704 в Массачусетском технологическом институте в 1957–58 годах ... Документ, определяющий условные выражения и предлагающий их использование в Алголе, был отправлен в отдел сообщений ACM. но был произвольно понижен в должности до письма в редакцию, потому что оно было очень коротким.
- ^ «Значение« объектно-ориентированного программирования »по мнению доктора Алана Кея» . 2003-07-23.
Тогда я не понимал чудовищной идеи LISP о материальном метаязыке, но был в некотором роде близок к идеям о расширяемых языках... Второй этап этого заключался в том, чтобы наконец понять LISP, а затем использовать это понимание, чтобы сделать намного лучше, меньше и больше. мощные и более поздние базовые структуры... ООП для меня означает только обмен сообщениями, локальное сохранение и защиту, а также сокрытие состояний-процессов и крайне позднее связывание всех вещей. Это можно сделать в Smalltalk и LISP. Возможно, есть и другие системы, в которых это возможно, но я о них не знаю.
- ^ Либерман, Генри; Хьюитт, Карл (июнь 1983 г.), «Сборщик мусора в реальном времени, основанный на времени жизни объектов» , Communications of the ACM , 26 (6): 419–429, CiteSeerX 10.1.1.4.8633 , doi : 10.1145/358141.358147 , hdl : 1721.1/6335 , S2CID 14161480
- ^ Эдсгер В. Дейкстра (1972), Скромный программист (EWD 340) (лекция на премию ACM Turing).
- ^ «Взгляд на Clojure и возрождение Lisp» .
- ^ «Жаргонный файл — Лисп» . Проверено 13 октября 2006 г.
- ^ Себеста, Роберт В. (2012). " "2.4 Функциональное программирование: LISP";"6.9 Типы списков";"15.4 Первый язык функционального программирования: LISP" ". Концепции языков программирования (печать) (10-е изд.). Бостон, Массачусетс, США: Аддисон-Уэсли. стр. 47–52, 281–284, 677–680. ISBN 978-0-13-139531-2 .
- ^ Примечание: так называемый «пунктирный список» — это лишь один из видов «неправильного списка». Другой вид — это «круговой список», в котором минус-ячейки образуют цикл. Обычно это представляется с помощью #n=(...) для обозначения целевой ячейки cons, которая будет иметь несколько ссылок, а #n# используется для ссылки на эту cons. Например, (#1=(ab) . #1#) обычно печатается как ((ab) ab) (без включения печати круговой структуры), но делает очевидным повторное использование ячейки cons. #1=(a . #1#) обычно не может быть напечатан, поскольку он имеет круглую форму, хотя (a...) иногда отображается, CDR ячейки cons, определенной #1=, является самим собой.
- ^ «CSE 341: Схема: цитата, квазицитата и метапрограммирование» . Cs.washington.edu. 22 февраля 1999 г. Проверено 15 ноября 2013 г.
- ↑ Квазицитата в Lisp. Архивировано 3 июня 2013 г. в Wayback Machine , Алан Боуден.
- ^ Время оценки — Общие расширения Lisp . Гну.орг. Проверено 17 июля 2013 г.
- ^ 3.2.2.3 Семантические ограничения в Common Lisp HyperSpec
- ^ 4.3. Абстракция управления (рекурсия против итерации) в учебнике по хорошему стилю программирования на Лиспе Кента Питмана и Питера Норвига , август 1993 г.
- ^ стр. 17 Боброу, 1986 г.
- ^ Вейч, стр. 108, 1988 г.
- ^ Провен, Лиам (29 марта 2022 г.). «Дикий мир операционных систем, отличных от C» . Регистр . Проверено 4 апреля 2024 г.
- ^ «Символика Open Genera 2.0» . GitHub Интернет-архив . 7 января 2020 г. Проверено 2 февраля 2022 г.
- ^ «Проект Interlisp.org» . Интерлисп.орг . 15 марта 2022 г. Проверено 2 февраля 2022 г.
- ^ «Интерлисп Медли» . Гитхаб . Март 2022 года . Проверено 2 февраля 2022 г.
- ^ Фрогги (1 августа 2021 г.). «Меццано» . Гитхаб . Проверено 2 февраля 2022 г.
- ^ Хартманн, Лукас Ф. (10 сентября 2015 г.). «Промежуточный» . Промежуточная ОС . Проверено 2 февраля 2022 г.
- ^ Хартманн, Лукас Ф. (11 июня 2021 г.). «Промежуточный» . Гитхаб . Проверено 2 февраля 2022 г.
- ^ Хинсли, Крис (23 февраля 2022 г.). «ХрисаЛисп» . Гитхаб . Проверено 2 февраля 2022 г.
- ^ Смит, Тони (21 августа 2013 г.). «Пионер микротехнологий Великобритании Крис Шелтон: разум, стоящий за Nascom 1» . Регистр . Проверено 2 февраля 2022 г.
Дальнейшее чтение
[ редактировать ]- Маккарти, Джон (12 февраля 1979 г.). «Реализация Лиспа» . История Лиспа . Стэнфордский университет . Проверено 17 октября 2008 г.
- Стил-младший, Гай Л.; Ричард П. Габриэль (1993). Эволюция Лиспа (PDF) . Вторая конференция ACM SIGPLAN по истории языков программирования. Нью-Йорк, штат Нью-Йорк: ACM. стр. 231–270. ISBN 0-89791-570-4 . Архивировано из оригинала (PDF) 12 октября 2006 г. Проверено 17 октября 2008 г.
- Вейч, Джим (1998). «История и описание CLOS». В Салусе, Питер Х. (ред.). Справочник по языкам программирования . Том. IV, Функциональные и логические языки программирования (1-е изд.). Индианаполис, Индиана: Техническое издательство Macmillan. стр. 107–158 . ISBN 1-57870-011-6 .
- Абельсон, Гарольд ; Сассман, Джеральд Джей ; Сассман, Джули (1996). Структура и интерпретация компьютерных программ (2-е изд.). МТИ Пресс. ISBN 0-262-01153-0 .
- My Lisp Experiences and the Development of GNU Emacs , стенограмма выступления Ричарда Столлмана , 28 октября 2002 г., на Международной конференции по Lisp
- Грэм, Пол (2004). Хакеры и художники. Большие идеи компьютерного века . О'Рейли. ISBN 0-596-00662-4 .
- Беркли, Эдмунд К .; Боброу, Дэниел Г. , ред. (март 1964 г.). Язык программирования LISP: его работа и приложения (PDF) . Кембридж, Массачусетс: MIT Press.
- Статья во многом основана на главе LISP — Простое введение : Беркли, Эдмунд К. (сентябрь 1964 г.). «Язык программирования Lisp: введение и оценка» . Компьютеры и автоматизация : 16-23 .
- Вайсман, Кларк (1967). Учебное пособие по LISP 1.5 (PDF) . Бельмонт, Калифорния: Dickenson Publishing Company Inc.
Внешние ссылки
[ редактировать ]- История
- История Лиспа - Джона Маккарти от 12 февраля 1979 г. история
- История Лиспа — история Герберта Стояна, составленная на основе документов (признанная Маккарти более полной, чем его собственная, см.: Ссылки на историю Маккарти )
- История LISP в Музее истории компьютеров
- Белл, Адам Гордон (2 мая 2022 г.). LISP в космосе, с Роном Гарретом . CoRecursive (подкаст, расшифровка, фотографии). об использовании программного обеспечения LISP на роботах НАСА .
- Кассель, Давид (22 мая 2022 г.). «Программист НАСА вспоминает отладку Lisp в глубоком космосе» . Новый стек .
- Ассоциации и встречи
- Ассоциация пользователей Лиспа
- Европейская встреча Common Lisp
- Европейский симпозиум по Лиспу
- Международная конференция по Лиспу
- Книги и учебные пособия
- Приведение SPEL в Lisp , вводное руководство в стиле комиксов
- О Лиспе , бесплатная книга Пола Грэма
- Практический Common Lisp , бесплатная версия Питера Сейбеля
- Лисп для Интернета
- Земля Лиспа
- Пусть над лямбдой
- Интервью
- Интервью по устной истории с Джоном Маккарти в Институте Чарльза Бэббиджа , Университет Миннесоты, Миннеаполис. Маккарти рассказывает о своей роли в развитии системы разделения времени в Массачусетском технологическом институте. Он также описывает свою работу в области искусственного интеллекта (ИИ), финансируемую Агентством перспективных исследовательских проектов, включая логический ИИ (LISP) и робототехнику.
- Интервью с Ричардом П. Габриэлем (подкаст)
- Ресурсы
- Лисп (язык программирования)
- Академические языки программирования
- Американские изобретения
- Динамически типизированные языки программирования
- Языки программирования с расширяемым синтаксисом
- Функциональные языки
- Семейство языков программирования Лисп
- Языки программирования
- Языки программирования, созданные в 1958 году.