Из Википедии, бесплатной энциклопедии
  (Перенаправлено с Лисп-1 на Лисп-2 )
Перейти к навигации Перейти к поиску

Common Lisp ( CL ) является диалектом языка программирования Lisp , опубликованный в ANSI стандарт документа ANSI INCITS 226-1994 (S20018) [1] (ранее X3.226-1994 (R1999) ). [2] Common Lisp Hyperspec , гиперссылками HTML - версия, была получена из стандарта ANSI Common Lisp. [3]

Язык Common Lisp был разработан как стандартизированный и улучшенный преемник Maclisp . К началу 1980-х несколько групп уже работали над разнообразными преемниками MacLisp: Lisp Machine Lisp (также известный как ZetaLisp), Spice Lisp , NIL и S-1 Lisp . Common Lisp стремился унифицировать, стандартизировать и расширить возможности этих диалектов MacLisp. Common Lisp - это не реализация, а спецификация языка . [4] Доступно несколько реализаций стандарта Common Lisp, включая бесплатное программное обеспечение с открытым исходным кодом и проприетарные продукты. [5] Common Lisp - универсальный,многопарадигмальный язык программирования . Он поддерживает сочетание процедурной , функциональной и объектно-ориентированной парадигм программирования . Как язык динамического программирования , он облегчает эволюционную и инкрементную разработку программного обеспечения с итеративной компиляцией в эффективные исполняемые программы. Эта инкрементальная разработка часто выполняется в интерактивном режиме, не прерывая работающее приложение.

Он также поддерживает необязательные аннотации типов и приведение типов, которые могут быть добавлены по мере необходимости на более поздних этапах профилирования и оптимизации, чтобы компилятор мог генерировать более эффективный код. Например, fixnumможет содержать распакованное целое число в диапазоне, поддерживаемом оборудованием и реализацией, что позволяет производить более эффективную арифметику, чем для больших целых чисел или типов произвольной точности. Точно так же компилятору можно указать для каждого модуля или функции, какой тип уровня безопасности требуется, с помощью объявлений оптимизации .

Common Lisp включает в себя CLOS , в систему объекта , которая поддерживает мультиметодов и комбинации методов. Это часто реализуется с помощью протокола метаобъектов .

Common Lisp расширяется с помощью стандартных функций, таких как макросы Lisp (преобразования кода) и макросы чтения (анализаторы ввода для символов).

Common Lisp обеспечивает частичную обратную совместимость с Maclisp и оригинальным Lisp Джона Маккарти . Это позволяет портировать старое программное обеспечение Lisp на Common Lisp. [6]

История [ править ]

Работа над Common Lisp началась в 1981 году после инициативы менеджера ARPA Боба Энгельмора по разработке единого стандартного диалекта Lisp сообщества. [7] Большая часть первоначального языкового дизайна была сделана через электронную почту. [8] [9] В 1982 году Гай Л. Стил-младший сделал первый обзор Common Lisp на симпозиуме ACM 1982 года по LISP и функциональному программированию. [10]

Документация на первом языке была опубликована в 1984 году как Common Lisp the Language (известный как CLtL1), первое издание. Второе издание (известное как CLtL2), опубликованное в 1990 году, включало многие изменения в язык, сделанные в процессе стандартизации ANSI Common Lisp: расширенный синтаксис LOOP, объектную систему Common Lisp, систему условий для обработки ошибок, интерфейс к симпатичный принтер и многое другое. Но CLtL2 не описывает окончательный стандарт ANSI Common Lisp и, следовательно, не является документацией по ANSI Common Lisp. Окончательный стандарт ANSI Common Lisp был опубликован в 1994 году. С тех пор никаких обновлений стандарта не публиковалось. Различные расширения и улучшения Common Lisp (например, Unicode, Concurrency, ввод-вывод на основе CLOS) были предоставлены реализациями и библиотеками.

Синтаксис [ править ]

Common Lisp - это диалект Lisp. Он использует S-выражения для обозначения как кода, так и структуры данных. Вызовы функций, макроформы и специальные формы записываются в виде списков с именем оператора первым, как в этих примерах:

 ( +  2  2 )  ; складывает 2 и 2, получая 4. Имя функции - «+». В Лиспе нет операторов как таковых.
 ( defvar  * x * )  ; Гарантирует, что переменная * x * существует  ,; не придавая ему значения. Звездочки являются частью  ; имя, по соглашению обозначающее специальную (глобальную) переменную.  ; Символ * x * также наделен свойством  : последующие его привязки являются скорее динамическими, чем лексическими.  ( setf  * x *  42.1 )  ; Устанавливает переменную * x * в значение с плавающей запятой 42.1
 ;; Определите функцию, возводящую число в  квадрат : ( defun  square  ( x )  ( *  x  x ))
 ;; Выполните функцию:  ( квадрат  3 )  ; Возвращает 9
 ;; Конструкция let создает область для локальных переменных. Здесь  ;; переменная 'a' привязана к 6, а переменная 'b' привязана  ;; до 4. Внутри 'let' находится 'тело', в котором возвращается последнее вычисленное значение.  ;; Здесь результат сложения a и b возвращается из выражения let.  ;; Переменные a и b имеют лексическую область видимости, если только символы не были  ;; помечены как специальные переменные (например, предыдущим DEFVAR).  ( пусть  (( a  6 )  ( b  4 ))  ( +  a  b ))  ; возвращает 10

Типы данных [ править ]

Common Lisp имеет много типов данных .

Скалярные типы [ править ]

Количество типов включают в себя целые числа , отношения , число с плавающей точкой и комплексные числа . [11] Common Lisp использует бигнумы для представления числовых значений произвольного размера и точности. Тип отношения точно представляет дроби, что не доступно на многих языках. Common Lisp автоматически сопоставляет числовые значения между этими типами по мере необходимости.

Тип символов Common Lisp не ограничивается символами ASCII . Большинство современных реализаций позволяют использовать символы Unicode . [12]

Тип символа является общим для языков Lisp, но в основном неизвестен за пределами их. Символ - это уникальный именованный объект данных, состоящий из нескольких частей: имени, значения, функции, списка свойств и пакета. Из них значение ячейки и функции клеток являются наиболее важными. Символы в Лиспе часто используются аналогично идентификаторам в других языках: для хранения значения переменной; однако есть много других применений. Обычно при оценке символа возвращается его значение. Некоторые символы оцениваются сами по себе, например, все символы в пакете ключевых слов являются самооценочными. Логические значения в Common Lisp представлены символами самооценки T и NIL. В Common Lisp есть пространства имен для символов, называемые «пакетами».

Доступен ряд функций для округления скалярных числовых значений различными способами. Функция roundокругляет аргумент до ближайшего целого числа, а промежуточные случаи округляются до четного целого числа. Функции truncate, floorи ceilingокругляют в сторону нуля, вниз или вверх соответственно. Все эти функции возвращают отброшенную дробную часть как вторичное значение. Например, (floor -2.5)дает -3, 0,5; (ceiling -2.5)дает −2, −0,5; (round 2.5)дает 2, 0,5; и (round 3.5)дает 4, −0,5.

Структуры данных [ править ]

Типы последовательностей в Common Lisp включают списки, векторы, битовые векторы и строки. Есть много операций, которые могут работать с любым типом последовательности.

Как и почти во всех других диалектах Лиспа, списки в Common Lisp состоят из conses , иногда называемых cons-ячейками или парами . Cons - это структура данных с двумя слотами, называемыми car и cdr . Список - это связанная цепочка заключений или пустой список. Автомобиль каждого минуса относится к члену списка (возможно, другого списка). Cdr каждого cons ссылается на следующие cons, за исключением последних cons в списке, cdr которых относится к nilзначению. Conses также можно легко использовать для реализации деревьев и других сложных структур данных; хотя обычно вместо этого рекомендуется использовать экземпляры структуры или класса. Также возможно создавать круговые структуры данных с помощью conses.

Common Lisp поддерживает многомерные массивы и при необходимости может динамически изменять размер настраиваемых массивов. Для матричной математики можно использовать многомерные массивы. Вектор представляет собой одномерный массив. Массивы могут нести в качестве членов любой тип (даже смешанные типы в одном массиве) или могут быть специализированы для хранения элементов определенного типа, как в векторе битов. Обычно поддерживаются только несколько типов. Многие реализации могут оптимизировать функции массива, когда используемый массив зависит от типа. Стандартными являются два типа специализированных массивов: строка - это вектор символов, а битовый вектор - это вектор бит .

Хеш-таблицы хранят ассоциации между объектами данных. Любой объект может использоваться как ключ или значение. Размер хеш-таблиц автоматически изменяется по мере необходимости.

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

Структуры , аналогичные по использованию структурам C и записям Паскаля , представляют произвольные сложные структуры данных с любым числом и типом полей (называемых слотами ). Структуры допускают одиночное наследование.

Классы похожи на структуры, но предлагают более динамичные функции и множественное наследование. (См. ЗАКРЫТЬ ). Классы были добавлены в Common Lisp поздно, и есть некоторое концептуальное совпадение со структурами. Объекты, созданные из классов, называются экземплярами . Особый случай - универсальные функции. Общие функции - это как функции, так и экземпляры.

Функции [ править ]

Common Lisp поддерживает первоклассные функции . Например, можно писать функции, которые также принимают другие функции в качестве аргументов или возвращают функции. Это позволяет описывать самые общие операции.

Библиотека Common Lisp в значительной степени полагается на такие функции высшего порядка. Например, sortфункция принимает реляционный оператор в качестве аргумента и ключевую функцию в качестве необязательного аргумента ключевого слова. Это можно использовать не только для сортировки любого типа данных, но и для сортировки структур данных по ключу.

 ;; Сортирует список с использованием функций> и <в качестве оператора отношения.  ( сортировать  ( список  5  2  6  3  1  4 )  # ' > )  ; Возвращает (6 5 4 3 2 1)  ( sort  ( list  5  2  6  3  1  4 )  # ' < )  ; Возврат (1 2 3 4 5 6)
 ;; Сортирует список по первому элементу каждого подсписка.  ( sort  ( list  ' ( 9  A )  ' ( 3  B )  ' ( 4  C ))  #' <  : key  # ' сначала )  ; Возврат ((3 B) (4 C) (9 A))

Модель оценки функций очень проста. Когда оценщик встречает форму, (f a1 a2...)он предполагает, что символ с именем f является одним из следующих:

  1. Специальный оператор (легко проверяется по фиксированному списку)
  2. Макрооператор (должен быть определен ранее)
  3. Имя функции (по умолчанию), которое может быть либо символом, либо подформой, начинающейся с символа lambda.

Если f - имя функции, то аргументы a1, a2, ..., an оцениваются в порядке слева направо, и функция обнаруживается и вызывается с этими значениями, указанными в качестве параметров.

Определение функций [ править ]

Макросdefun определяет функцию , где определение функции задает имя функции, имен аргументов, а тело функции:

 ( defun  квадрат  ( x )  ( *  x  x ))

Определения функций могут включать директивы компилятора , известные как объявления , которые предоставляют компилятору подсказки о параметрах оптимизации или типах данных аргументов. Они также могут включать строки документации (docstrings), которые система Lisp может использовать для предоставления интерактивной документации:

 ( DEFUN  квадрат  ( х )  «вычисляет квадрат одного флоат х.»  ( DECLARE  ( одного поплавка  х )  ( оптимизируют  ( скорость  3 )  ( отладка  0 )  ( безопасность  1 )))  ( одного поплавка ( * х х )))    

Анонимные функции ( функциональные литералы ) определяются с помощью lambdaвыражений, например, (lambda (x) (* x x))для функции, которая возводит в квадрат свой аргумент. Стиль программирования Lisp часто использует функции высшего порядка, для которых полезно предоставить анонимные функции в качестве аргументов.

Локальные функции могут быть определены с помощью fletи labels.

 ( флет  (( квадрат  ( x )  ( *  x  x )))  ( квадрат  3 ))

Есть несколько других операторов, связанных с определением функций и манипулированием ими. Например, функция может быть скомпилирована с compileоператором. (Некоторые системы Lisp по умолчанию запускают функции с использованием интерпретатора, если не указано иное, другие компилируют каждую функцию).

Определение общих функций и методов [ править ]

Макрос defgenericопределяет общие функции . Общие функции - это набор методов . Макрос defmethodопределяет методы.

Методы могут специализировать свои параметры на стандартных классах CLOS , системных классах , классах структуры или отдельных объектах. Для многих типов существуют соответствующие системные классы .

Когда вызывается универсальная функция, множественная отправка определяет эффективный метод для использования.

 ( defgeneric  add  ( a  b ))
 ( DEFMETHOD  добавить  (( число ) ( б номер )) ( + б ))      
 ( defmethod  add  (( a  vector )  ( b  number ))  ( map  'vector  ( lambda  ( n )  ( +  n  b ))  a ))
 ( defmethod  add  (( a  vector )  ( b  vector ))  ( map  'vector  #' +  a  b ))
( DEFMETHOD  добавить  (( строка ) ( б строка )) ( конкатенации «строка б ))       
 ( прибавляем  2  3 )  ; возвращает 5  ( добавить  # ( 1  2  3  4 )  7 )  ; возвращает # (8 9 10 11)  ( добавить  # ( 1  2  3  4 )  # ( 4  3  2  1 ))  ; возвращает # (5 5 5 5)  ( добавить  «ОБЩИЙ»  «LISP» )  ; возвращает "COMMON LISP"

Универсальные функции также являются типом данных первого класса . У универсальных функций и методов гораздо больше возможностей, чем описано выше.

Пространство имен функции [ править ]

Пространство имен для имен функций отделено от пространства имен для переменных данных. Это ключевое различие между Common Lisp и Scheme . Для Common Lisp, операторы , которые определяют имена в функции имен включают defun, flet, labels, defmethodи defgeneric.

Чтобы передать функцию по имени в качестве аргумента другой функции, необходимо использовать functionспециальный оператор, обычно обозначаемый как #'. Первый sortпример выше относится к функции, названной символом >в пространстве имен функции, с кодом #'>. И наоборот, чтобы вызвать функцию, переданную таким образом, нужно использовать funcallоператор для аргумента.

Модель оценки схемы проще: существует только одно пространство имен, и все позиции в форме оцениваются (в любом порядке), а не только аргументы. Поэтому код, написанный на одном диалекте, иногда сбивает с толку программистов, более опытных в другом. Например, многие программисты Common Lisp любят использовать описательные имена переменных, такие как список или строка, которые могут вызвать проблемы в Scheme, поскольку они будут локально затенять имена функций.

Вопрос о том, является ли отдельное пространство имен для функций преимуществом, является источником разногласий в сообществе Lisp. Обычно это называют дебатами Лисп-1 против Лисп-2 . Lisp-1 относится к модели Scheme, а Lisp-2 относится к модели Common Lisp. Эти названия были придуманы Ричардом П. Габриэлем и Кентом Питманом в статье 1988 года , в которой проводится подробное сравнение этих двух подходов. [13]

Несколько возвращаемых значений [ править ]

Common Lisp поддерживает концепцию нескольких значений , [14] , где любое выражение всегда имеет одно первичное значение , но он может также иметь любое число вторичных значений , которые могут быть получены и проверены заинтересованными абонентами. Эта концепция отличается от возврата значения списка, поскольку вторичные значения являются полностью необязательными и передаются через выделенный побочный канал. Это означает, что вызывающие абоненты могут оставаться в полном неведении о наличии вторичных значений, если они им не нужны, и это делает удобным использование механизма передачи информации, которая иногда бывает полезной, но не всегда необходимой. Например,

  • TRUNCATEФункции [15] округляет заданное число до целого числа к нулю. Однако он также возвращает остаток в качестве вторичного значения, что позволяет очень легко определить, какое значение было усечено. Он также поддерживает необязательный параметр делителя, который можно использовать для тривиального выполнения евклидова деления :
( let  (( x  1266778 )  ( y  458 ))  ( привязка нескольких значений  ( частный  остаток )  ( усечение  x  y )  ( формат  nil  "~ A, деленный на ~ A ~ A остаток ~ A"  x  y  частный  остаток )) );;;; => "1266778 делить на 458 дает 2765 остаток 408"
  • GETHASH[16] возвращает значение ключа в ассоциативной карте или значение по умолчанию, в противном случае, и вторичное логическое значение, указывающее, было ли найдено значение. Таким образом, код, который не заботится о том, было ли значение найдено или предоставлено по умолчанию, может просто использовать его как есть, но когда такое различие важно, он может проверить вторичное логическое значение и отреагировать соответствующим образом. Оба варианта использования поддерживаются одним и тем же вызовом, и ни один из них не обременен и не ограничен другим. Наличие этой функции на уровне языка устраняет необходимость проверять наличие ключа или сравнивать его с нулевым значением, как это было бы сделано на других языках.
( defun  get-answer  ( библиотека )  ( библиотека ответов gethash  42 ))  ( defun  the-answer-1  ( библиотека )  ( format  nil  "Ответ ~ A"  ( библиотека get-answer  ))) ;;;; Возвращает «Ответ 42», если ОТВЕТ отсутствует в БИБЛИОТЕКЕ.( defun  the-answer-2  ( библиотека )  ( multi-value-bind  ( answer  sure-p )  ( get-answer  library )  ( if  ( not  sure-p )  "Я не знаю"  ( формат  nil)  "Ответ ~ А "  ответ )))) ;;;; Возвращает "Я не знаю", если ОТВЕТ отсутствует в БИБЛИОТЕКЕ.

Несколько значений поддерживаются несколькими стандартными формами, наиболее распространенными из которых являются MULTIPLE-VALUE-BINDспециальные формы для доступа к вторичным значениям и VALUESдля возврата нескольких значений:

( defun  magic-8-ball  ()  «Вернуть прогноз с вероятностью в качестве вторичного значения»  ( значения  «Outlook хороший»  ( случайный  1,0 )));;;; => "Outlook хороший" ;;;; => 0,3187

Другие типы [ править ]

Другие типы данных в Common Lisp включают:

  • Имена путей представляют файлы и каталоги в файловой системе . Средство именования путей Common Lisp является более общим, чем соглашения об именах файлов в большинстве операционных систем, что делает доступ программ на Lisp к файлам широко переносимым между различными системами.
  • Потоки ввода и вывода представляют собой источники и приемники двоичных или текстовых данных, такие как терминал или открытые файлы.
  • Common Lisp имеет встроенный генератор псевдослучайных чисел (PRNG). Объекты случайного состояния представляют собой многократно используемые источники псевдослучайных чисел, позволяя пользователю заполнить ГПСЧ или заставить его воспроизвести последовательность.
  • Условия - это тип, используемый для представления ошибок, исключений и других «интересных» событий, на которые программа может реагировать.
  • Классы являются объектами первого класса и сами являются экземплярами классов, называемых классами метаобъектов ( для краткости метаклассами ).
  • Таблицы чтения - это тип объекта, который управляет тем, как средство чтения Common Lisp анализирует текст исходного кода. Контролируя, какая таблица для чтения используется при считывании кода, программист может изменить или расширить синтаксис языка.

Сфера [ править ]

Подобно программам на многих других языках программирования, программы Common Lisp используют имена для обозначения переменных, функций и многих других типов объектов. Именованные ссылки зависят от области применения.

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

Область действия относится к набору обстоятельств, при которых определено, что имя имеет определенную привязку.

Определители объема [ править ]

Обстоятельства, определяющие область действия Common Lisp, включают:

  • расположение ссылки в выражении. Если это крайняя левая позиция соединения, это относится к специальному оператору, макросу или привязке функции, в противном случае - к привязке переменной или чему-то еще.
  • вид выражения, в котором имеет место ссылка. Например, (go x)означает передачу управления метке x, тогда как (print x)относится к переменной x. Обе области xмогут быть активны в одной и той же области текста программы, поскольку метки тегов находятся в отдельном пространстве имен от имен переменных. Специальная форма или макроформа имеет полный контроль над значениями всех символов в ее синтаксисе. Например, в (defclass x (a b) ())определении класса (a b)- это список базовых классов, поэтому эти имена ищутся в пространстве имен классов и xне являются ссылкой на существующую привязку, а являются именем нового производного класса. от aи b. Эти факты вытекают исключительно из семантикиdefclass. Единственный общий факт об этом выражении - это то, что оно defclassотносится к привязке макроса; все остальное до defclass.
  • расположение ссылки в тексте программы. Например, если ссылка на переменную xзаключена в конструкцию привязки, такую ​​как a, letкоторая определяет привязку для x, то ссылка находится в области, созданной этой привязкой.
  • для ссылки на переменную, независимо от того, был ли символ переменной, локально или глобально, объявлен специальным. Это определяет, разрешается ли ссылка в лексической среде или в динамической среде.
  • конкретный экземпляр среды, в которой разрешена ссылка. Среда - это словарь времени выполнения, который сопоставляет символы привязкам. Каждый вид ссылки использует свою среду. Ссылки на лексические переменные разрешаются в лексической среде и так далее. С одной и той же ссылкой может быть связано несколько сред. Например, благодаря рекурсии или использованию нескольких потоков одновременно может существовать несколько активаций одной и той же функции. Эти активации используют один и тот же текст программы, но каждая имеет свой собственный экземпляр лексической среды.

Чтобы понять, к чему относится символ, программист Common Lisp должен знать, какой тип ссылки выражается, какую область видимости она использует, если это ссылка на переменную (динамическая или лексическая область видимости), а также ситуацию во время выполнения: in в какой среде была разрешена ссылка, где была введена привязка в среду и т. д.

Виды среды [ править ]

Глобальный [ править ]

Некоторые среды в Лиспе распространены глобально. Например, если определен новый тип, то он впоследствии будет известен повсюду. Ссылки на этот тип ищите в этой глобальной среде.

Динамический [ править ]

Одним из типов среды в Common Lisp является динамическая среда. Привязки, установленные в этой среде, имеют динамическую протяженность, что означает, что привязка устанавливается в начале выполнения некоторой конструкции, такой как letблок, и исчезает, когда эта конструкция завершает выполнение: ее время жизни привязано к динамической активации и деактивации Блок. Однако динамическая привязка не только видна внутри этого блока; он также виден всем функциям, вызываемым из этого блока. Этот тип видимости известен как неопределенная область видимости. Привязки, которые демонстрируют динамическую протяженность (время жизни, связанное с активацией и деактивацией блока) и неопределенную область действия (видимую для всех функций, вызываемых из этого блока), как говорят, имеют динамическую область видимости.

Common Lisp поддерживает переменные с динамической областью видимости, которые также называются специальными переменными. Некоторые другие виды привязок также обязательно имеют динамическую область видимости, например, перезапуск и теги перехвата. Привязки функций не могут иметь динамическую область видимости с помощью flet(которая предоставляет только привязки функций с лексической областью видимости), но объекты функций (объект первого уровня в Common Lisp) могут быть назначены переменным с letдинамической областью видимости, привязаны с помощью динамической области видимости, а затем вызваны с помощью funcallили APPLY.

Динамическая область видимости чрезвычайно полезна, поскольку она добавляет ссылочной ясности и дисциплины глобальным переменным . В информатике к глобальным переменным относятся неодобрительно, как к потенциальным источникам ошибок, поскольку они могут создавать специальные, скрытые каналы связи между модулями, ведущие к нежелательным и неожиданным взаимодействиям.

В Common Lisp специальная переменная, имеющая привязку только верхнего уровня, ведет себя так же, как глобальная переменная в других языках программирования. В нем можно сохранить новое значение, и это значение просто заменяет то, что находится в привязке верхнего уровня. Неосторожная замена значения глобальной переменной лежит в основе ошибок, вызванных использованием глобальных переменных. Однако другой способ работы со специальной переменной - присвоить ей новую локальную привязку внутри выражения. Иногда это называют «повторным связыванием» переменной. Привязка переменной с динамической областью видимости временно создает новое место в памяти для этой переменной и связывает имя с этим расположением. Пока эта привязка действует, все ссылки на эту переменную относятся к новой привязке; предыдущая привязка скрыта. Когда выполнение выражения привязки завершается,временная ячейка памяти исчезла, и старая привязка была обнаружена с сохранением исходного значения. Конечно, можно вложить несколько динамических привязок для одной и той же переменной.

В реализациях Common Lisp, которые поддерживают многопоточность, динамические области видимости специфичны для каждого потока выполнения. Таким образом, специальные переменные служат абстракцией для локального хранилища потоков. Если один поток повторно связывает специальную переменную, это повторное связывание не влияет на эту переменную в других потоках. Значение, хранящееся в привязке, может быть получено только потоком, создавшим эту привязку. Если каждый поток связывает какую-то специальную переменную *x*, то *x*ведет себя как локальное хранилище потока. Среди потоков, которые не связываются повторно *x*, он ведет себя как обычный глобальный поток : все эти потоки относятся к одной и той же привязке верхнего уровня *x*.

Динамические переменные могут использоваться для расширения контекста выполнения дополнительной контекстной информацией, которая неявно передается от функции к функции без необходимости появляться в качестве дополнительного параметра функции. Это особенно полезно, когда передача управления должна проходить через уровни несвязанного кода, который просто не может быть расширен дополнительными параметрами для передачи дополнительных данных. В подобной ситуации обычно требуется глобальная переменная. Эта глобальная переменная должна быть сохранена и восстановлена, чтобы схема не нарушалась при рекурсии: об этом позаботится динамическое повторное связывание переменной. И эта переменная должна быть локальной для потока (иначе должен использоваться большой мьютекс), чтобы схема не нарушалась под потоками: реализации динамической области также могут позаботиться об этом.

В библиотеке Common Lisp есть много стандартных специальных переменных. Например, все стандартные потоки ввода-вывода хранятся в привязках верхнего уровня известных специальных переменных. Стандартный поток вывода хранится в * стандартном выводе *.

Предположим, функция foo записывает в стандартный вывод:

 ( defun  foo  ()  ( формат  t  «Привет, мир» ))

Чтобы записать его вывод в символьной строке, * стандартный вывод * может быть привязан к строковому потоку и вызван:

 ( с выводом в строку  ( * стандартный вывод * )  ( foo ))
-> «Привет, мир»; собранный вывод возвращается в виде строки

Лексический [ править ]

Common Lisp поддерживает лексические среды. Формально привязки в лексической среде имеют лексическую область видимости и могут иметь неопределенную или динамическую степень, в зависимости от типа пространства имен. Лексическая область видимости означает, что видимость физически ограничена блоком, в котором установлена ​​привязка. Ссылки, которые не текстуально (т. Е. Лексически) встроены в этот блок, просто не видят эту привязку.

Теги в TAGBODY имеют лексическую область видимости. Выражение (GO X) ошибочно, если оно не встроено в TAGBODY, который содержит метку X. Однако привязки меток исчезают, когда TAGBODY завершает свое выполнение, потому что они имеют динамическую протяженность. Если этот блок кода повторно вводится при вызове лексического замыкания , то тело этого замыкания не может пытаться передать управление тегу через GO:

 ( defvar  * stashed * )  ;; будет выполнять функцию ( tagbody  ( setf  * stashed *  ( lambda  ()  ( go  some-label )))  ( go  end-label )  ;; пропустить (print "Hello")  some-label  ( print  "Hello" )  end-label )  ->  Ноль

Когда TAGBODY выполняется, он сначала оценивает форму setf, которая сохраняет функцию в специальной переменной * stashed *. Затем (go end-label) передает управление на end-label, пропуская код (выведите «Hello»). Поскольку конечная метка находится в конце тела тега, тело тега завершается, давая NIL. Предположим, что теперь вызывается ранее запомненная функция:

 ( funcall  * stashed * )  ;; Ошибка!

Это ошибочная ситуация. Ответом одной реализации является состояние ошибки, содержащее сообщение «GO: tagbody для тега SOME-LABEL уже оставлено». Функция попыталась оценить (go some-label), который лексически встроен в тело тега, и преобразуется в метку. Однако tagbody не выполняется (его размер закончился), и поэтому передача управления не может произойти.

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

Лексическая привязка - это режим привязки по умолчанию для переменных Common Lisp. Для отдельного символа его можно переключить в динамическую область видимости либо локальным объявлением, либо глобальным объявлением. Последнее может происходить неявно посредством использования таких конструкций, как DEFVAR или DEFPARAMETER. Это важная конвенция в Common Lisp программирования , что специальные (т.е. с динамической областью видимости) переменные имеют имена , которые начинаются и заканчиваются звездочкой сигилы * в том, что называется « Earmuff конвенции». [17] При соблюдении этого соглашения создается отдельное пространство имен для специальных переменных, так что переменные, которые должны быть лексическими, не могут быть случайно сделаны специальными.

Лексическая область полезна по нескольким причинам.

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

Во-вторых, лексическая область видимости (в сочетании с неопределенной степенью) порождает лексическое замыкание , которое, в свою очередь, создает целую парадигму программирования, сосредоточенную вокруг использования функций, являющихся объектами первого класса, что лежит в основе функционального программирования.

В-третьих, что, возможно, наиболее важно, даже если лексические замыкания не используются, использование лексической области видимости изолирует программные модули от нежелательных взаимодействий. Из-за ограниченной видимости лексические переменные являются закрытыми. Если один модуль A связывает лексическую переменную X и вызывает другой модуль B, ссылки на X в B не будут случайно разрешаться в X, привязанный к A. B просто не имеет доступа к X. Для ситуаций, в которых дисциплинированные взаимодействия через переменную являются желательно, Common Lisp предоставляет специальные переменные. Специальные переменные позволяют модулю A устанавливать привязку для переменной X, которая видна другому модулю B, вызываемому из A. Возможность сделать это является преимуществом, и возможность предотвратить это также является преимуществом; следовательно, Common Lisp поддерживает как лексическую, так и динамическую область видимости .

Макросы [ править ]

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

Типичное использование макросов в Лиспе:

  • новые управляющие структуры (пример: конструкции цикла, конструкции ветвления)
  • ограничивающие и связывающие конструкции
  • упрощенный синтаксис для сложного и повторяющегося исходного кода
  • формы определения верхнего уровня с побочными эффектами времени компиляции
  • программирование, управляемое данными
  • встроенные предметно-ориентированные языки (примеры: SQL, HTML, Prolog)
  • неявные формы завершения

Различные стандартные функции Common Lisp также должны быть реализованы в виде макросов, например:

  • стандартная setfабстракция, позволяющая настраивать расширения операторов присваивания / доступа во время компиляции
  • with-accessors, with-slots, with-open-fileИ другие подобные WITHмакросы
  • В зависимости от реализации ifили condмакрос построен на другом, специальном операторе; whenи unlessсостоят из макросов
  • Мощный loopпредметно-ориентированный язык

Макросы определяются макросом defmacro . Специальный оператор macrolet позволяет определять локальные (лексический контекстные) макрокоманды. Также можно определить макросы для символов с помощью define-symbol-macro и symbol-macrolet .

Книга Пола Грэма « О Лиспе» подробно описывает использование макросов в Common Lisp. Книга Дуга Хойта « Let Over Lambda» расширяет обсуждение макросов, утверждая, что «макросы - это единственное величайшее преимущество Lisp как языка программирования и единственное величайшее преимущество любого языка программирования». Хойт приводит несколько примеров итеративной разработки макросов.

Пример использования макроса для определения новой структуры управления [ править ]

Макросы позволяют программистам на Лиспе создавать новые синтаксические формы на языке. Типичное использование - создание новых структур управления. Пример макроса предоставляет untilконструкцию цикла. Синтаксис:

(до тестовой формы *)

Определение макроса до :

( defmacro  до  ( test  & body  body )  ( let  (( start-tag  ( gensym  "START" ))  ( end-tag  ( gensym  "END" )))  ` ( tagbody  , start-tag  ( when  , test  ( go  , end- tag ))  ( progn  , @ body )  ( go  , start-tag )  , end-tag )))

tagbody - это примитивный специальный оператор Common Lisp, который дает возможность присваивать имена тегам и использовать форму go для перехода к этим тегам. Обратная кавычка ` представляет собой нотацию, которая предоставляет шаблоны кода, где значения форм, которым предшествует запятая, заполняются. Формы, которым предшествует запятая и знак at, сращиваются . Форма tagbody проверяет конечное условие. Если условие истинно, выполняется переход к конечному тегу. В противном случае выполняется указанный основной код, а затем выполняется переход к начальному тегу.

Пример использования макроса, указанного выше, до :

( до  ( =  ( случайное  10 )  0 )  ( напишите  "Привет" ))

Код можно расширить с помощью функции macroexpand-1 . Расширение для приведенного выше примера выглядит так:

( TAGBODY  #: START1136  ( WHEN  ( ZEROP  ( RANDOM  10 ))  ( GO  #: END1137 ))  ( PROGN  ( WRITE-LINE  "привет" ))  ( GO  #: START1136 )  #: END1137 )

Во время раскрытия макроса значение переменной test равно (= (random 10) 0), а значение тела переменной - ((строка записи "Hello")) . Тело - это список форм.

Символы обычно автоматически изменяются. Расширение использует TAGBODY с двумя метками. Символы для этих этикеток вычисляются GENSYM и не интернированы ни в какой пакет. Две формы go используют эти теги для перехода. Поскольку tagbody является примитивным оператором в Common Lisp (а не макросом), он не будет расширен во что-то еще. В развернутой форме используется макрос when , который также будет развернут. Полное раскрытие исходной формы называется обходом кода .

В полностью развернутой ( проходящей ) форме форма when заменяется примитивом, если :

( TAGBODY  #: START1136  ( IF  ( ZEROP  ( RANDOM  10 ))  ( PROGN  ( GO  #: END1137 ))  NIL )  ( PROGN  ( WRITE-LINE  "привет" ))  ( GO  #: START1136 ))  #: END1137 )

Все макросы должны быть раскрыты, прежде чем исходный код, содержащий их, можно будет оценить или скомпилировать в обычном режиме. Макросы можно рассматривать как функции, которые принимают и возвращают S-выражения - аналогично абстрактным синтаксическим деревьям , но не ограничиваясь ими. Эти функции вызываются перед оценщиком или компилятором для создания окончательного исходного кода. Макросы написаны на обычном Common Lisp и могут использовать любой доступный Common Lisp (или сторонний) оператор.

Переменный захват и затенение [ править ]

Макросы Common Lisp способны к так называемому захвату переменных , когда символы в теле расширения макроса совпадают с символами в вызывающем контексте, что позволяет программисту создавать макросы, в которых различные символы имеют особое значение. Термин « захват переменной» несколько вводит в заблуждение, потому что все пространства имен уязвимы для нежелательного захвата, включая пространство имен оператора и функции, пространство имен метки tagbody, тег catch, обработчик условий и пространства имен перезапуска.

Захват переменных может привести к дефектам программного обеспечения. Это происходит одним из следующих двух способов:

  • В первом случае расширение макроса может непреднамеренно создать символическую ссылку, которая, как предполагал создатель макроса, разрешит в глобальном пространстве имен, но код, в котором раскрывается макрос, предоставляет локальное, теневое определение, которое крадет эту ссылку. Назовем это захватом типа 1.
  • Второй способ, захват типа 2, прямо противоположен: некоторые аргументы макроса представляют собой фрагменты кода, предоставленные вызывающим макросом, и эти фрагменты кода написаны таким образом, что они ссылаются на окружающие привязки. Однако макрос вставляет эти фрагменты кода в расширение, которое определяет свои собственные привязки, которые случайно захватывают некоторые из этих ссылок.

Диалект Scheme в Lisp обеспечивает систему записи макросов, которая обеспечивает ссылочную прозрачность, которая устраняет оба типа проблем захвата. Этот тип макросистемы иногда называют «гигиеничным», в частности, его сторонники (которые считают макросистемы, не решающие эту проблему автоматически, антисанитарными). [ необходима цитата ]

В Common Lisp макросигиена обеспечивается одним из двух способов.

Один из подходов - использовать генетические символы : гарантированно уникальные символы, которые можно использовать в макрорасширении без угрозы захвата. Использование генсимов в определении макроса - это ручная работа, но можно написать макросы, которые упростят создание и использование генсимов. Генсимы легко решают захват типа 2, но они не применимы к захвату типа 1 таким же образом, потому что расширение макроса не может переименовать мешающие символы в окружающем коде, которые захватывают его ссылки. Gensyms можно использовать для обеспечения стабильных псевдонимов для глобальных символов, необходимых для макрорасширения. Расширение макроса будет использовать эти секретные псевдонимы, а не общеизвестные имена, поэтому переопределение хорошо известных имен не окажет вредного воздействия на макрос.

Другой подход - использовать пакеты. Макрос, определенный в собственном пакете, может просто использовать внутренние символы этого пакета в своем расширении. Использование пакетов касается захвата типа 1 и типа 2.

Однако пакеты не решают проблему захвата 1-го типа ссылок на стандартные функции и операторы Common Lisp. Причина в том, что использование пакетов для решения проблем захвата вращается вокруг использования частных символов (символов в одном пакете, которые не импортируются или иным образом не становятся видимыми в других пакетах). В то время как символы библиотеки Common Lisp являются внешними и часто импортируются или становятся видимыми в пользовательских пакетах.

Ниже приведен пример нежелательного захвата в пространстве имен оператора, происходящего при раскрытии макроса:

 ;; расширение UNTIL позволяет свободно использовать DO  ( defmacro  until  ( expression  & body  body )  ` ( do  ()  ( , expression )  , @ body )) ;; macrolet устанавливает привязку лексического оператора для DO  ( macrolet  (( do  ( ... )  ...  something  else  ... ))  ( until  ( =  ( random  10 )  0 )  ( write-line  "Hello" )))

untilМакрос будет расширяться в форме, вызовы doкоторых предназначен для обозначения стандартного макроса Common Lisp do. Однако в этом контексте doможет иметь совершенно другое значение, поэтому untilможет работать некорректно.

Common Lisp решает проблему дублирования стандартных операторов и функций, запрещая их переопределение. Поскольку он переопределяет стандартный оператор do, предыдущий фактически является фрагментом несовместимого Common Lisp, который позволяет реализациям диагностировать и отклонять его.

Система условий [ править ]

Система условий отвечает за обработку исключений в Common Lisp. [18] Он предоставляет условия , обработчики и перезапуск . Условия - это объекты, описывающие исключительную ситуацию (например, ошибку). Если указано условие , система Common Lisp ищет обработчик для этого типа условия и вызывает обработчик. обработчик теперь может выполнять поиск перезапусков и использовать один из этих перезапусков для автоматического устранения текущей проблемы, используя такую ​​информацию, как тип условия и любую соответствующую информацию, предоставленную как часть объекта условия, и вызывать соответствующую функцию перезапуска.

Эти перезапуски, если они не обрабатываются кодом, могут быть представлены пользователям (как часть пользовательского интерфейса, например, отладчика), чтобы пользователь мог выбрать и вызвать один из доступных перезапусков. Поскольку обработчик условий вызывается в контексте ошибки (без раскрутки стека), полное восстановление после ошибки возможно во многих случаях, когда другие системы обработки исключений уже завершили бы текущую процедуру. Сам отладчик также можно настроить или заменить с помощью *debugger-hook*динамической переменной. Код, находящийся в формах защиты от размотки, таких как финализаторы, также будет выполняться соответствующим образом, несмотря на исключение.

В следующем примере (с использованием Symbolics Genera ) пользователь пытается открыть файл в функциональном тесте Lisp, вызываемом из Read-Eval-Print-LOOP ( REPL ), когда файл не существует. Система Lisp предлагает четыре перезапуска. Пользователь выбирает Retry OPEN, используя перезапуск с другим именем пути, и вводит другое имя пути (lispm-init.lisp вместо lispm-int.lisp). Код пользователя не содержит кода обработки ошибок. Весь код обработки ошибок и перезапуска обеспечивается системой Lisp, которая может обрабатывать и исправлять ошибку, не прерывая пользовательский код.

Команда: (test "> zippy> lispm-int.lisp")Ошибка: файл не найден. Для lispm:> zippy> lispm-int.lisp.newestLMFS: OPEN-LOCAL-LMFS-1 Аргумент 0: #P "lispm:> zippy> lispm-int.lisp.newest"sA, <Resume>: повторить попытку OPEN для lispm:> zippy> lispm-int.lisp.newestsB: повторить попытку OPEN, используя другой путьsC, <Abort>: вернуться на верхний уровень Lisp на сервере TELNET.sD: перезапустить процесс Терминал TELNET-> Повторите попытку OPEN, используя другой путьИспользуйте вместо этого имя пути [по умолчанию lispm:> zippy> lispm-int.lisp.newest]: lispm:> zippy> lispm-init.lisp.newest... программа продолжается

Common Lisp Object System (CLOS) [ править ]

Common Lisp включает набор инструментов для объектно-ориентированного программирования , Common Lisp Object System или CLOS , которая является одной из самых мощных объектных систем, доступных на любом языке. Например, Питер Норвиг объясняет, сколько шаблонов проектирования проще реализовать на динамическом языке с помощью функций CLOS (множественное наследование, миксины, мультиметоды, метаклассы, комбинации методов и т. Д.). [19] Было предложено включить несколько расширений Common Lisp для объектно-ориентированного программирования в стандарт ANSI Common Lisp, но в конечном итоге CLOS была принята как стандартная объектная система для Common Lisp. CLOS - это система динамических объектов с множественной отправкой.и множественное наследование , и радикально отличается от средств ООП, имеющихся в статических языках, таких как C ++ или Java . В качестве динамической объектной системы CLOS позволяет изменять общие функции и классы во время выполнения. Можно добавлять и удалять методы, можно добавлять и переопределять классы, можно обновлять объекты для изменений класса и можно изменять класс объектов.

CLOS интегрирован в ANSI Common Lisp. Общие функции могут использоваться как обычные функции и представляют собой первоклассный тип данных. Каждый класс CLOS интегрирован в систему типов Common Lisp. Многие типы Common Lisp имеют соответствующий класс. Для Common Lisp существует больше возможностей использовать CLOS. В спецификации не говорится, реализуются ли условия с помощью CLOS. Пути и потоки могут быть реализованы с помощью CLOS. Эти дополнительные возможности использования CLOS для ANSI Common Lisp не являются частью стандарта. Фактические реализации Common Lisp используют CLOS для имен путей, потоков, ввода-вывода, условий, реализации самого CLOS и многого другого.

Компилятор и интерпретатор [ править ]

Интерпретатор Лиспа напрямую выполняет исходный код Лиспа, предоставленный как объекты Лиспа (списки, символы, числа, ...), считанные из s-выражений. Компилятор Lisp генерирует байт-код или машинный код из исходного кода Lisp. Common Lisp позволяет компилировать как отдельные функции Lisp в памяти, так и компилировать целые файлы во внешний скомпилированный код ( файлы fasl ).

Несколько реализаций более ранних диалектов Лиспа предоставляли как интерпретатор, так и компилятор. К сожалению, часто семантика была иной. Эти более ранние Лиспы реализовали лексическую область видимости в компиляторе и динамическую область видимости в интерпретаторе. Common Lisp требует, чтобы и интерпретатор, и компилятор по умолчанию использовали лексическую область видимости. Стандарт Common Lisp описывает семантику интерпретатора и компилятора. Компилятор может быть вызван с использованием функции compile для отдельных функций и с использованием файла компиляции функции для файлов. Common Lisp позволяет объявления типов и предоставляет способы влиять на политику генерации кода компилятора. Для последних различных качеств оптимизации могут быть заданы значения от 0 (не важно) до 3 (наиболее важно): скорость, пространство , безопасность , отладка и скорость компиляции .

Существует также функция для оценки коды Lisp: eval. evalпринимает код как предварительно проанализированные s-выражения, а не, как в некоторых других языках, как текстовые строки. Таким образом, код может быть построен с помощью обычных функций Лиспа для построения списков и символов, а затем этот код может быть оценен с помощью функции eval. Несколько реализаций Common Lisp (например, Clozure CL и SBCL) реализуются evalс использованием своего компилятора. Таким образом код компилируется, даже если он оценивается с помощью функции eval.

Компилятор файла вызывается с помощью функции compile-file . Сгенерированный файл со скомпилированным кодом называется файлом fasl (из быстрой загрузки ). Эти файлы fasl, а также файлы исходного кода могут быть загружены с функцией load в работающую систему Common Lisp. В зависимости от реализации компилятор файлов генерирует байт-код (например, для виртуальной машины Java ), код языка C (который затем компилируется с помощью компилятора C) или, напрямую, собственный код.

Реализации Common Lisp можно использовать в интерактивном режиме, даже если код полностью компилируется. Таким образом, идея интерпретируемого языка не применима к интерактивному Common Lisp.

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

Некоторые специальные операторы специально предназначены для интерактивной разработки; например, defvarприсвоит значение предоставленной переменной только в том случае, если она еще не была привязана, при defparameterэтом всегда будет выполнять присвоение. Это различие полезно при интерактивной оценке, компиляции и загрузке кода в живом изображении.

Также предоставляются некоторые функции, помогающие писать компиляторы и интерпретаторы. Символы состоят из объектов первого уровня и напрямую управляются пользовательским кодом. progvСпециальный оператор позволяет создавать лексические привязки программно, а пакеты также манипулируемо. Компилятор Lisp доступен во время выполнения для компиляции файлов или отдельных функций. Это упрощает использование Lisp в качестве промежуточного компилятора или интерпретатора для другого языка.

Примеры кода [ править ]

Парадокс дня рождения [ править ]

Следующая программа вычисляет наименьшее количество людей в комнате, для которых вероятность уникальных дней рождения составляет менее 50% ( парадокс дня рождения , где для 1 человека вероятность, очевидно, составляет 100%, для 2 - 364/365 и т. Д. ). Ответ - 23.

По соглашению константы в Common Lisp заключаются в символы +.

( defconstant  + размер года +  365 )( defun  birthday-paradox  ( вероятность-  число-людей )  ( let  (( новая-вероятность  ( *  ( /  ( -  + размер года +  количество людей )  + размер года + )  вероятность )))  ( if  ( <  новое -вероятность  0,5 )  ( 1+  количество людей )  ( парадокс дня рождения  новая вероятность  ( 1+  количество людей )))))

Вызов функции примера с помощью REPL (цикл печати Read Eval):

CL-USER> (парадокс дня рождения 1.0 1)23

Сортировка списка объектов человека [ править ]

Мы определяем класс personи метод для отображения имени и возраста человека. Затем мы определяем группу людей как список personобъектов. Затем мы перебираем отсортированный список.

( defclass  person  ()  (( name  : initarg  : name  : accessor  person-name )  ( age  : initarg  : age  : accessor  person-age ))  ( : документация  "Класс PERSON со слотами NAME и AGE." ))( defmethod  display  (( объект  person )  stream )  «Отображение объекта PERSON в потоке вывода.»  ( with-slots  ( name  age )  object  ( format  stream  «~ a (~ a)»  name  age )))( defparameter  * group *  ( list  ( make-instance  'person  : name  "Bob"  : age  33 )  ( make-instance  ' person  : name  "Chris"  : age  16 )  ( make-instance  'person  : name  "Ash"  : age  23 ))  «Список предметов ЛИЦО.» )( dolist  ( person  ( sort  ( copy-list  * group * )  # ' >  : key  #' person-age ))  ( отображать  человека  * стандартный вывод * )  ( terpri ))

Он печатает три имени по убыванию возраста.

Боб (33)Ясень (23)Крис (16)

Возведение в степень возведением в квадрат [ править ]

Демонстрируется использование макроса LOOP:

( defun  power  ( x  n )  ( цикл  с  результатом  =  1  while  ( plusp  n )  when  ( oddp  n )  do  ( setf  result  ( *  result  x ))  do  ( setf  x  ( *  x  x )  n  ( truncate  n  2 ))  finally  ( вернуть  результат )))

Пример использования:

CL-USER> (мощность 2 200)1606938044258990275541962092341162602522202993782792835301376

Сравните со встроенным возведением в степень:

CL-USER> (= (expt 2 200) (power 2 200))Т

Найдите список доступных оболочек [ править ]

WITH-OPEN-FILE - это макрос, который открывает файл и предоставляет поток. Когда форма возвращается, файл автоматически закрывается. FUNCALL вызывает объект функции. LOOP собирает все строки, соответствующие предикату.

( defun  list-matching-lines  ( предикат файла  ) «Возвращает список строк в файле, для которых примененный к строке предикат возвращает T.» ( with-open-file ( файл потока ) ( цикл для строки = ( чтение- линия потока ноль ноль ) в то время как линии , когда ( FUNCALL сказуемое линия ) собирать его )))                    

Функция AVAILABLE-SHELLS вызывает вышеупомянутую функцию LIST-MATCHING-LINES с именем пути и анонимной функцией в качестве предиката. Предикат возвращает путь к оболочке или NIL (если строка не является именем файла оболочки).

( defun  available-shells  ( & optional  ( file  #p "/ etc / shells" ))  ( файл списка совпадающих строк  ( lambda ( line ) ( and ( plusp ( length line )) ( char = ( char line 0 ) # \ / ) ( путь ( строка-справа-обрезка ' ( # \ пробел # \ табуляция ) строка ))))))                

Пример результатов (в Mac OS X 10.6):

CL-USER  >  ( доступные-оболочки ) ( #P "/ bin / bash"  #P "/ bin / csh"  #P "/ bin / ksh"  #P "/ bin / sh"  #P "/ bin / tcsh"  #P "/ bin / zsh" )

Сравнение с другими Лиспами [ править ]

Common Lisp чаще всего сравнивают и противопоставляют Scheme - хотя бы потому, что это два самых популярных диалекта Lisp. Scheme предшествует CL и исходит не только из той же традиции Lisp, но и от некоторых из тех же инженеров - Гай Л. Стил , с которым Джеральд Джей Суссман разработал Scheme, возглавлял комитет по стандартизации Common Lisp.

Common Lisp - это язык программирования общего назначения, в отличие от вариантов Lisp, таких как Emacs Lisp и AutoLISP, которые являются языками расширения, встроенными в определенные продукты (GNU Emacs и AutoCAD соответственно). В отличие от многих более ранних Lisp, Common Lisp (как и Scheme ) по умолчанию использует область видимости лексических переменных как для интерпретируемого, так и для компилируемого кода.

Большинство систем Лиспа, чьи конструкции способствовали развитию Common Lisp, такие как ZetaLisp и Franz Lisp, использовали переменные с динамической областью видимости в своих интерпретаторах и переменные с лексической областью видимости в своих компиляторах. Scheme ввел в Lisp единственное использование переменных с лексической областью видимости; вдохновение из АЛГОЛА 68 . CL также поддерживает переменные с динамической областью видимости, но они должны быть явно объявлены как «специальные». Нет различий в области видимости между интерпретаторами и компиляторами ANSI CL.

Common Lisp иногда называют Lisp-2, а Scheme - Lisp-1 , имея в виду использование CL отдельных пространств имен для функций и переменных. (Фактически, CL имеет много пространств имен, например, для тегов go, имен блоков и loopключевых слов). Между сторонниками CL и Scheme существует давняя полемика по поводу компромиссов, связанных с несколькими пространствами имен. В Scheme (в широком смысле) необходимо избегать указания имен переменных, которые конфликтуют с функциями; Функции схемы часто имеют аргументы с именами lis, lstили lystтак , чтобы не конфликтовать с системной функцией.list. Однако в CL необходимо явно ссылаться на пространство имен функции при передаче функции в качестве аргумента - что также является обычным явлением, как в sortприведенном выше примере.

CL также отличается от Scheme обработкой логических значений. Схема использует специальные значения #t и #f для представления истины и лжи. CL следует старому соглашению Lisp об использовании символов T и NIL, причем NIL также обозначает пустой список. В CL любое значение, отличное от NIL, обрабатывается условными операторами как истинное, например if, тогда как в схеме все значения , отличные от # f, обрабатываются как истинные. Эти соглашения позволяют некоторым операторам на обоих языках служить как предикатами (отвечая на вопрос с логическим значением), так и возвращать полезное значение для дальнейших вычислений, но в Scheme значение '(), которое эквивалентно NIL в Common Lisp, оценивается как истинное. в логическом выражении.

Наконец, документы стандартов Scheme требуют оптимизации хвостового вызова , чего нет в стандарте CL. Большинство реализаций CL действительно предлагают оптимизацию хвостового вызова, хотя часто только тогда, когда программист использует директиву оптимизации. Тем не менее, общий CL стиль кодирования не способствует повсеместное использование рекурсии , что схема стиль предпочитает-то , что программист Схема выразит с хвостом рекурсии, пользователь CL обычно выражают с помощью итеративного выражения в do, dolist, loopили (совсем недавно) с iterateупаковка.

Реализации [ править ]

См. Категории " Реализации Common Lisp" .

Common Lisp определяется спецификацией (например, Ada и C ), а не одной реализацией (например, Perl ). Существует множество реализаций и стандартные детали, в которых они могут действительно различаться.

Кроме того, реализации, как правило, идут с расширениями, которые предоставляют функции, не охваченные стандартом:

  • Интерактивный верхний уровень (REPL)
  • Вывоз мусора
  • Отладчик, шаговый двигатель и инспектор
  • Слабые структуры данных (хеш-таблицы)
  • Расширяемые последовательности
  • Расширяемый цикл
  • Доступ к среде
  • ЗАКРЫТЬ Мета-объектный протокол
  • Расширяемые потоки на основе CLOS
  • Система условий на основе CLOS
  • Сетевые потоки
  • Постоянное закрытие
  • Поддержка Unicode
  • Интерфейс на иностранном языке (часто на C)
  • Интерфейс операционной системы
  • Интерфейс Java
  • Потоки и многопроцессорность
  • Доставка приложений (приложения, динамические библиотеки)
  • Сохранение изображений

Бесплатные библиотеки программного обеспечения с открытым исходным кодом были созданы для поддержки расширений Common Lisp переносимым способом, и в первую очередь их можно найти в репозиториях Common-Lisp.net [20] и CLOCC (Common Lisp Open Code Collection) [21 ] проекты.

Реализации Common Lisp могут использовать любое сочетание компиляции собственного кода, компиляции или интерпретации байтового кода. Common Lisp был разработан для поддержки инкрементных компиляторов , компиляторов файлов и блочных компиляторов. Стандартные объявления для оптимизации компиляции (например, встраивание функций или специализация типов) предлагаются в спецификации языка. Большинство реализаций Common Lisp компилируют исходный код в собственный машинный код . Некоторые реализации могут создавать (оптимизированные) автономные приложения. Другие компилируются в интерпретируемый байт-код, который менее эффективен, чем собственный код, но упрощает переносимость двоичного кода. Некоторые компиляторы компилируют код Common Lisp в код C. Ошибочное представление о том, что Lisp является чисто интерпретируемым языком, скорее всего, связано с тем, что среды Lisp предоставляют интерактивные подсказки и этот код компилируется один за другим, поэтапно. В Common Lisp широко используется инкрементная компиляция.

Некоторые реализации на основе Unix ( CLISP , SBCL ) могут использоваться как язык сценариев ; то есть вызывается системой прозрачно, как интерпретатор оболочки Perl или Unix . [22]

Список реализаций [ править ]

Коммерческие реализации [ править ]

Аллегро Common Lisp
для Microsoft Windows, FreeBSD, Linux, Apple macOS и различных вариантов UNIX. Allegro CL предоставляет интегрированную среду разработки (IDE) (для Windows и Linux) и обширные возможности для доставки приложений.
Жидкий Common Lisp
ранее назывался Lucid Common Lisp . Только обслуживание, новых выпусков нет.
LispWorks
для Microsoft Windows, FreeBSD, Linux, Apple macOS, iOS, Android и различных вариантов UNIX. LispWorks предоставляет интегрированную среду разработки (IDE) (доступную для большинства платформ, но не для iOS и Android) и обширные возможности для доставки приложений.
мокл
для iOS, Android и macOS.
Open Genera
для DEC Alpha.
Scieneer Common Lisp
который разработан для высокопроизводительных научных вычислений.

Свободно распространяемые реализации [ править ]

Вооруженный медведь Common Lisp (ABCL)
Реализация CL, работающая на виртуальной машине Java . [23] Он включает компилятор байтового кода Java и обеспечивает доступ к библиотекам Java из CL. Это было прежде всего компонента вооруженных Медведя J редактора .
CLISP
Реализация компиляции байт-кода, переносимая и работающая в нескольких Unix и Unix-подобных системах (включая macOS ), а также в Microsoft Windows и некоторых других системах.
Закрытие CL (CCL)
Первоначально это была бесплатная вилка Macintosh Common Lisp с открытым исходным кодом . Как следует из этой истории, CCL был написан для Macintosh, но Clozure CL теперь работает на macOS , FreeBSD , Linux , Solaris и Windows . 32- и 64-битные порты x86 поддерживаются на каждой платформе. Дополнительно есть порты Power PC для Mac OS и Linux. CCL ранее был известен как OpenMCL, но это имя больше не используется, чтобы избежать путаницы с версией Macintosh Common Lisp с открытым исходным кодом.
CMUCL
Первоначально из Университета Карнеги-Меллона , в настоящее время поддерживается как бесплатное программное обеспечение с открытым исходным кодом группой добровольцев. CMUCL использует быстрый компилятор машинного кода. Он доступен в Linux и BSD для Intel x86; Linux для Alpha; macOS для Intel x86 и PowerPC; и Solaris, IRIX и HP-UX на своих собственных платформах.
Корман Common Lisp
для Microsoft Windows. В январе 2015 года Corman Lisp был опубликован под лицензией MIT. [24]
Встраиваемый Common Lisp (ECL)
ECL включает интерпретатор и компилятор байт-кода. Он также может компилировать код Lisp в машинный код через компилятор C. Затем ECL компилирует код Lisp в C, компилирует код C с помощью компилятора C и затем может загрузить полученный машинный код. Также можно встраивать ECL в программы на C и код на C в программы Common Lisp.
GNU Common Lisp (GCL)
В GNU Lisp компилятор проекта. Еще не полностью совместимый с ANSI, GCL, тем не менее, является предпочтительной реализацией для нескольких крупных проектов, включая математические инструменты Maxima , AXIOM и (исторически) ACL2 . GCL работает в Linux под одиннадцатью различными архитектурами, а также под Windows, Solaris и FreeBSD .
Macintosh Common Lisp (MCL)
Версия 5.2 для компьютеров Apple Macintosh с процессором PowerPC под управлением Mac OS X является открытым исходным кодом. RMCL (на основе MCL 5.2) работает на компьютерах Apple Macintosh на базе Intel с использованием двоичного транслятора Rosetta от Apple.
ManKai Common Lisp (MKCL)
Филиал ECL . MKCL подчеркивает надежность, стабильность и общее качество кода за счет сильно переработанной, изначально многопоточной системы времени выполнения. В Linux MKCL представляет собой полностью совместимую с POSIX систему времени выполнения.
Мовиц
Реализует среду Lisp для компьютеров x86, не полагаясь на какую-либо базовую ОС.
Поплог
Poplog реализует версию CL с POP-11 и, возможно, Prolog и Standard ML (SML), что позволяет программировать на разных языках. Для всех языком реализации является POP-11, который компилируется постепенно. Он также имеет встроенный редактор, подобный Emacs, который взаимодействует с компилятором.
Steel Bank Common Lisp (SBCL)
Ветка от CMUCL . «Вообще говоря, SBCL отличается от CMU CL большим упором на ремонтопригодность». [25] SBCL работает на платформах CMUCL, кроме HP / UX; кроме того, он работает в Linux для AMD64, PowerPC, SPARC, MIPS, Windows x86 [26] и имеет экспериментальную поддержку для работы в Windows AMD64. SBCL по умолчанию не использует интерпретатор; все выражения компилируются в машинный код, если пользователь не включит интерпретатор. Компилятор SBCL генерирует быстрый машинный код в соответствии с предыдущей версией The Computer Language Benchmarks Game . [27]
Ufasoft Common Lisp
порт CLISP для платформы Windows с ядром, написанным на C ++.

Другие реализации [ править ]

Остин Киото Common Lisp
эволюция Киото Common Lisp от Билла Шелтер
Бабочка Common Lisp
реализация, написанная на схеме для многопроцессорного компьютера BBN Butterfly [28] [29]
CLICC
компилятор Common Lisp to C [30]
CLOE
Common Lisp для ПК от Symbolics
Codemist Common Lisp
используется для коммерческой версии системы компьютерной алгебры Axiom [31] [32]
ExperCommon Lisp
ранняя реализация для Apple Macintosh от ExperTelligence
Золотой Common Lisp
реализация для ПК от GoldHill Inc. [33] [34]
Ибуки Общий Лисп
коммерческая версия Kyoto Common Lisp
Киотский Common Lisp
первый компилятор Common Lisp, который использовал C в качестве целевого языка. GCL, ECL и MKCL происходят от этой реализации Common Lisp.
L
небольшая версия Common Lisp для встроенных систем, разработанная IS Robotics, теперь iRobot [35]
Машины на Лиспе (от Symbolics , TI [36] [37] и Xerox [38] )
предоставили реализации Common Lisp в дополнение к их родному диалекту Lisp (Lisp Machine Lisp или Interlisp). Также был доступен CLOS. Symbolics предоставляет расширенную версию Common Lisp. [39] [40] [41]
Процион Common Lisp
реализация для Windows и Mac OS, которую Франц использовал для своего Windows-порта Allegro CL.
Звездный сапфир обыкновенный LISP
реализация для ПК
SubL
вариант Common Lisp, используемый для реализации системы Cyc, основанной на знаниях [42]
Common Lisp верхнего уровня
ранняя реализация для параллельного выполнения [43]
WCL
реализация разделяемой библиотеки [44] [45]
Vax Common Lisp
Реализация Digital Equipment Corporation, работающая в системах VAX с VMS или ULTRIX
XLISP
реализация, написанная Дэвидом Бетцем [46]

Приложения [ править ]

Common Lisp используется для разработки исследовательских приложений (часто в области искусственного интеллекта), для быстрой разработки прототипов или для развернутых приложений.

Common Lisp используется во многих коммерческих приложениях, включая Yahoo! Интернет-магазин магазина, в котором изначально участвовал Пол Грэм, а затем был переписан на C ++ и Perl. [47] К другим примечательным примерам относятся:

  • ACT-R , когнитивная архитектура, используемая в большом количестве исследовательских проектов.
  • Помощник авторизатора, [48] [49] большая основанная на правилах система, используемая American Express для анализа кредитных запросов.
  • Cyc , долгосрочный проект по созданию системы, основанной на знаниях, которая предоставляет огромное количество здравого смысла.
  • Gensym G2 , экспертная система реального времени и механизм бизнес-правил [50]
  • Genworks GDL , основанный на ядре Gendl с открытым исходным кодом.
  • Среда разработки для серии видеоигр Jak and Daxter , разработанная Naughty Dog .
  • Система поиска дешевых билетов ITA Software , используемая туристическими сайтами, такими как Orbitz и Kayak.com, и такими авиакомпаниями, как American Airlines , Continental Airlines и US Airways .
  • Mirai , набор для 3D-графики. Он использовался для анимации лица Голлума в фильме «Властелин колец: Две башни».
  • Opusmodus - это система музыкальной композиции, основанная на Common Lisp, используемая в компьютерной композиции [51]
  • Система проверки прототипов (PVS), механизированная среда для формальной спецификации и проверки.
  • PWGL - это сложная среда визуального программирования, основанная на Common Lisp, используемая в компьютерной композиции и синтезе звука. [52]
  • Piano, полный пакет анализа самолетов, написанный на Common Lisp [53], используемый такими компаниями, как Boeing , Airbus , Northrop Grumman . [54]
  • Grammarly , англоязычная платформа для улучшения письма, имеет ядро ​​грамматического движка, написанное на Common Lisp [55]
  • Инструмент динамического анализа и перепланирования (DART), который, как говорят, один окупил с 1991 по 1995 годы все тридцать лет инвестиций DARPA в исследования ИИ.
  • « Удаленный агент » НАСА (Лаборатории реактивного движения) , отмеченная наградами [56] программа Common Lisp [57] для автопилота космического корабля Deep Space One.
  • SigLab, платформа Common Lisp для обработки сигналов, используемая в противоракетной обороне, построенная Raytheon [53]
  • Система планирования миссии NASA Mars Pathfinder [58]
  • СПАЙК, система диспетчеризации для земляных или космических обсерваторий и спутников, в частности с Хаббла космического телескопа., [59] написана в Common Lisp [60]
  • Common Lisp использовался для создания прототипа сборщика мусора Microsoft .NET Common Language Runtime [61]
  • Первоначальная версия Reddit , хотя позже разработчики перешли на Python из-за отсутствия библиотек для Common Lisp, согласно официальному сообщению в блоге соучредителя Reddit Стива Хаффмана . [62]

Также существуют приложения с открытым исходным кодом, написанные на Common Lisp, такие как:

  • ACL2 , полнофункциональная автоматическая программа доказательства теорем для аппликативного варианта Common Lisp.
  • Аксиома , сложная система компьютерной алгебры .
  • Maxima , сложная система компьютерной алгебры , основанная на Macsyma.
  • OpenMusic - это объектно-ориентированная среда визуального программирования, основанная на Common Lisp, используемая в компоновке с помощью компьютера .
  • Pgloader , загрузчик данных для PostgreSQL, который был переписан с Python на Common Lisp. [63]
  • Stumpwm , оконный менеджер X11, управляемый клавиатурой, полностью написанный на Common Lisp.

См. Также [ править ]

  • Common Lisp - язык
  • На Лиспе
  • Практический Common Lisp

Ссылки [ править ]

  1. ^ «Действия по стандартам ANSI - 28 декабря 2018 г.» (PDF) . ansi.org .
  2. ^ Цитируется из обложки цитируемого стандарта. ANSI INCITS 226-1994 [S2008], продается на странице стандартных документов. Заархивировано 27 сентября 2020 г., в Wayback Machine .
  3. ^ "CLHS: О Common Lisp HyperSpec (TM)" . lispworks.com .
  4. ^ «CLHS: Раздел 1.1.2» . lispworks.com .
  5. ^ "Общие реализации Лиспа: Обзор" . Архивировано из оригинального 21 апреля 2012 года . Проверено 22 декабря 2007 года .
  6. ^ "Старые программы LISP все еще работают в Common Lisp" . Проверено 13 мая 2015 года .
  7. ^ «Корни« Ю-Шианг Лисп », письмо от Джона Л. Уайта, 1982» . cmu.edu .
  8. ^ "Почтовый индекс" . cl-su-ai.lisp.se .
  9. ^ Рефлекторная Anti-LOOPism и другие Электронная почта Явления: устные, письменные и электронные шаблоны в компьютерно-опосредованной коммуникации, JoAnne Йейтс и Ванда J. Орликовски, 1993. Архивации 8 августа 2012, в Wayback Machine
  10. ^ Младший, Стил; Л., Гай (15 августа 1982 г.). Обзор COMMON LISP . Lfp '82. ACM. С. 98–107. DOI : 10.1145 / 800068.802140 . ISBN 9780897910828. S2CID  14517358 .
  11. Редди, Абхишек (22 августа 2008 г.). «Особенности Common Lisp» .
  12. ^ «Поддержка Unicode» . Common Lisp Wiki . Проверено 21 августа 2008 года .
  13. ^ Ричард П. Габриэль; Кент М. Питман (июнь 1988 г.). «Технические вопросы разделения функциональных ячеек и ячеек значений» . Лисп и символьные вычисления . 1 (1): 81–101. DOI : 10.1007 / bf01806178 . S2CID 26716515 . 
  14. ^ «Common Lisp Hyperspec: Раздел 3.1.7» .
  15. ^ "Common Lisp Hyperspec: Функция FLOOR" .
  16. ^ "Common Lisp Hyperspec: Аксессор GETHASH" .
  17. ^ "Let Over Lambda" . letoverlambda.com .
  18. Питер Сейбел (7 апреля 2005 г.). Практический Common Lisp . Апресс. ISBN 978-1-59059-239-7.
  19. ^ «Шаблоны проектирования в динамическом программировании» . norvig.com .
  20. ^ Common-Lisp.net
  21. ^ Коллекция открытого кода Common Lisp
  22. ^ «32.6. Быстрая доставка с помощью CLISP» . clisp.cons.org .
  23. ^ "Вооруженный медведь Common Lisp" .
  24. ^ «Теперь доступны исходники Corman Lisp» .
  25. ^ «История и авторское право» . Стальной банк Common Lisp .
  26. ^ "Платформенный стол" . Стальной банк Common Lisp .
  27. ^ «Какие программы самые быстрые? - Компьютерная языковая тестовая игра» . 20 мая 2013 г. Архивировано из оригинального 20 мая 2013 года .
  28. ^ "Пакет: lang / lisp / impl / bbn /" . cs.cmu.edu .
  29. ^ "Последние разработки в Butterfly Lisp, 1987, AAAI Proceedings" (PDF) . aaai.org .
  30. ^ Burkart, O .; Goerigk, W .; Кнутцен, Х. (22 июня 1992 г.). «CLICC: новый подход к компиляции программ Common Lisp на C». CiteSeerX 10.1.1.38.1282 .  Цитировать журнал требует |journal=( помощь )
  31. ^ "codemist.co.uk" . lisp.codemist.co.uk .
  32. Аксиома, 30-летний горизонт, стр. 43
  33. ^ "Разработчик Golden Common Lisp" . goldhill-inc.com .
  34. ^ Golden Common LISP: практический подход, Дэвид Дж. Стил, июнь 2000 г., издательство Addison Wesley Publishing Company
  35. ^ Брукс, Родни А .; др., др. (22 июня 1995 г.). «L - Common Lisp для встроенных систем». CiteSeerX 10.1.1.2.1953 .  Цитировать журнал требует |journal=( помощь )
  36. ^ Концепции программирования TI Explorer
  37. ^ Справочник по TI Explorer Lisp
  38. ^ Medley Примечание к выпуску лисповского
  39. ^ "Symbolics Common Lisp Dictionary" (PDF) . trailing-edge.com .
  40. ^ "Символика общих концепций языка Lisp" (PDF) . trailing-edge.com .
  41. ^ "Символические конструкции программирования Common Lisp" (PDF) . trailing-edge.com .
  42. ^ "Ссылка SubL - Cycorp" . cyc.com .
  43. ^ "Top Level Inc. - Группа сохранения программного обеспечения" . softwarepreservation.org .
  44. ^ WCL: Доставка эффективных приложений Common Lisp под Unix, Труды конференции ACM 1992 года по LISP и функциональному программированию , страницы 260–269
  45. ^ "commonlisp.net :: WCL" . pgc.com . Архивировано из оригинала на 5 апреля 2016 года . Проверено 25 марта 2016 года .
  46. ^ "Пакет: lang / lisp / impl / xlisp /" . cs.cmu.edu .
  47. ^ «Превосходя средние показатели» . paulgraham.com .
  48. ^ «Помощник авторизатора» (PDF) . aaai.org .
  49. American Express Authorizer's Assistant. Архивировано 12 декабря 2009 г. в Wayback Machine.
  50. ^ Разработка приложений в реальном времени. Архивировано 2 августа 2016 г. на Wayback Machine . Gensym. Проверено 16 августа 2016 года.
  51. ^ Opusmodus - Главная
  52. ^ PWGL - Главная . . Проверено 17 июля 2013 года.
  53. ^ a b "Аэрокосмическая промышленность - Common Lisp" . lisp-lang.org .
  54. ^ [1] Пользователи фортепиано, получено со страницы производителя.
  55. ^ [2] Grammarly.com, Запуск Lisp в рабочей среде
  56. ^ "Удаленный агент" . ti.arc.nasa.gov .
  57. ^ http://www.flownet.com/gat/jpl-lisp.html
  58. ^ "Приложения клиентов Franz Inc: НАСА" . franz.com .
  59. ^ Пиковое планирование и система расписания . Stsci.edu. Проверено 17 июля 2013 года.
  60. ^ "Приложения клиентов Franz Inc: Институт космического телескопа" . franz.com .
  61. ^ "Как все начиналось ... AKA Рождение CLR" . microsoft.com .
  62. ^ Хаффман, Стив. "на шепелявку" . Проголосовали . Архивировано из оригинала на 17 мая 2018 года . Проверено 11 мая 2019 года .
  63. ^ https://tapoueh.org/blog/2014/05/why-is-pgloader-so-much-faster/

Библиография [ править ]

Хронологический список опубликованных (или готовящихся к публикации) книг о Common Lisp (языке) или о программировании на Common Lisp (особенно о программировании на основе ИИ).

  • Гай Л. Стил : Common Lisp the Language, 1-е издание , Digital Press, 1984, ISBN 0-932376-41-X 
  • Родни Аллен Брукс : Программирование на Common Lisp , John Wiley and Sons Inc, 1985, ISBN 0-471-81888-7 
  • Ричард П. Габриэль : Производительность и оценка систем Lisp , MIT Press, 1985, ISBN 0-262-57193-5 , PDF 
  • Роберт Виленски : Common LISPcraft , WW Norton & Co., 1986, ISBN 0-393-95544-3 
  • Юджин Чарняк , Кристофер К. Рисбек , Дрю В. Макдермотт , Джеймс Р. Михан : Программирование искусственного интеллекта, 2-е издание , Лоуренс Эрлбаум, 1987, ISBN 0-89859-609-2 
  • Венди Л. Милнер : Common Lisp: Учебное пособие , Prentice Hall, 1987, ISBN 0-13-152844-0 
  • Дебора Г. Татар : Руководство программиста по Common Lisp , Longman Higher Education, 1987, ISBN 0-13-728940-5 
  • Тайити Юаса , Масами Хагия : Введение в Common Lisp , Elsevier Ltd, 1987, ISBN 0-12-774860-1 
  • Christian Queinnec , Jerome Chailloux : Lisp Evolution and Standardization , Ios Pr Inc., 1988, ISBN 90-5199-008-1 
  • Тайити Юаса , Ричард Вейхрауч , Ясуко Китадзима : Common Lisp Drill , Academic Press Inc, 1988, ISBN 0-12-774861-X 
  • Уэйд Л. Хеннесси : Common Lisp , McGraw-Hill Inc., 1989, ISBN 0-07-028177-7 
  • Тони Хэзмер , Джон Доминк : Программирование Common Lisp для искусственного интеллекта , Addison-Wesley Educational Publishers Inc, 1989, ISBN 0-201-17579-7 
  • Соня Э. Кин : объектно-ориентированное программирование в Common Lisp: Руководство программиста по CLOS , Addison-Wesley, 1989, ISBN 0-201-17589-4 
  • Дэвид Джей Стил : Golden Common Lisp: практический подход , Addison Wesley, 1989, ISBN 0-201-41653-0 
  • Дэвид С. Турецки : Common Lisp: мягкое введение в символические вычисления , Бенджамин-Каммингс, 1989, ISBN 0-8053-0492-4 . Интернет / PDF Перепечатка Dover (2013) ISBN 978-0486498201  
  • Кристофер К. Рисбек , Роджер С. Шенк : рассуждение , основанное на прецедентах , Лоуренс Эрлбаум, 1989, ISBN 0-89859-767-6 
  • Патрик Уинстон , Бертольд Хорн : Лисп, 3-е издание , Аддисон-Уэсли, 1989, ISBN 0-201-08319-1 , Интернет 
  • Джерард Газдар , Крис Меллиш : Обработка естественного языка в LISP: Введение в компьютерную лингвистику , Addison-Wesley Longman Publishing Co., 1990, ISBN 0-201-17825-7 
  • Патрик Р. Харрисон : Common Lisp и искусственный интеллект , Prentice Hall PTR, 1990, ISBN 0-13-155243-0 
  • Тимоти Кошманн : Common Lisp Companion , John Wiley & Sons, 1990, ISBN 0-471-50308-8 
  • W. Ричард Старк : LISP, Lore and Logic , Springer Verlag New York Inc., 1990, ISBN 978-0-387-97072-1 , PDF 
  • Молли М. Миллер , Эрик Бенсон : стиль и дизайн Lisp , Digital Press, 1990, ISBN 1-55558-044-0 
  • Гай Л. Стил : Common Lisp the Language , 2-е издание , Digital Press, 1990, ISBN 1-55558-041-6 , Web 
  • Робин Джонс, Клайв Мейнард , Ян Стюарт: Искусство программирования на Лисп , Springer Verlag New York Inc., 1990, ISBN 978-3-540-19568-9 , PDF 
  • Стивен Л. Танимото : Элементы искусственного интеллекта с использованием Common Lisp , Computer Science Press, 1990, ISBN 0-7167-8230-8 
  • Питер Ли : Темы в продвинутой реализации языка , MIT Press, 1991, ISBN 0-262-12151-4 
  • Джон Х. Райли : рабочая тетрадь Common Lisp , Prentice Hall, 1991, ISBN 0-13-155797-1 
  • Питер Норвиг : Парадигмы программирования искусственного интеллекта: примеры использования Common Lisp , Морган Кауфманн, 1991, ISBN 1-55860-191-0 , Web 
  • Грегор Кичалес , Джим де Ривьер , Даниэль Г. Боброу : Искусство протокола метаобъектов , MIT Press, 1991, ISBN 0-262-61074-4 
  • Джо А. Лоулесс , Молли М. Миллер : Понимание CLOS: объектная система Common Lisp , Digital Press, 1991, ISBN 0-13-717232-X 
  • Марк Уотсон: Модули Common Lisp: искусственный интеллект в эпоху нейронных сетей и теории хаоса , Springer Verlag New York Inc., 1991, ISBN 0-387-97614-0 , PDF 
  • Джеймс Л. Нойес : Искусственный интеллект с Common Lisp: основы символьной и числовой обработки , Jones & Bartlett Pub, 1992, ISBN 0-669-19473-5 
  • Стюарт С. Шапиро : ОБЩИЙ LISP: интерактивный подход , Computer Science Press, 1992, ISBN 0-7167-8218-9 , Web / PDF 
  • Кеннет Д. Форбус , Йохан де Клер : Построение решателей проблем , MIT Press, 1993, ISBN 0-262-06157-0 
  • Андреас Пепке : объектно-ориентированное программирование: перспектива CLOS , MIT Press, 1993, ISBN 0-262-16136-2 
  • Пол Грэм : On Lisp , Prentice Hall, 1993, ISBN 0-13-030552-9 , Web / PDF 
  • Пол Грэм : ANSI Common Lisp , Prentice Hall, 1995, ISBN 0-13-370875-6 
  • Отто Майер : Программы на Common Lisp , немецкий, Spektrum Akademischer Verlag, 1995, ISBN 3-86025-710-2 
  • Стивен Слэйд : объектно-ориентированный Common Lisp , Prentice Hall, 1997, ISBN 0-13-605940-6 
  • Ричард П. Габриэль : Паттерны программного обеспечения: рассказы сообщества разработчиков программного обеспечения , Oxford University Press, 1998, ISBN 0-19-512123-6 , PDF 
  • Тайити Юаса , Хироши Г. Окуно : Advanced Lisp Technology , CRC, 2002, ISBN 0-415-29819-9 
  • Дэвид Б. Ламкинс : Успешный Лисп: Как понять и использовать Common Lisp , bookfix.com, 2004. ISBN 3-937526-00-5 , Интернет 
  • Питер Сейбел : Практический Common Lisp , Apress, 2005. ISBN 1-59059-239-5 , Интернет 
  • Дуг Хойт : Let Over Lambda , Lulu.com, 2008, ISBN 1-4357-1275-7 , Интернет 
  • Джордж Ф. Люгер , Уильям А. Стаблфилд : алгоритмы искусственного интеллекта, структуры данных и идиомы в Prolog, Lisp и Java , Addison Wesley, 2008, ISBN 0-13-607047-7 , PDF 
  • Конрад Барски : Земля Лиспа: научитесь программировать на Лиспе, по одной игре за раз! , No Starch Press, 2010, ISBN 1-59327-200-6 , Интернет 
  • Павел Пенев : Lisp Web Tales , Leanpub, 2013, Интернет
  • Эдмунд Вайц : Common Lisp Recipes , Apress, 2015, ISBN 978-1-484211-77-9 , Интернет 
  • Патрик М. Крузенотто : Функциональное программирование и метапрограммирование, Interaktiv in Common Lisp , Springer Fachmedien Wiesbaden 2016, ISBN 978-3-658-13743-4 , Интернет 

Внешние ссылки [ править ]

  • Quicklisp - очень популярный и качественный менеджер библиотек для Common Lisp.
  • Список Awesome CL , тщательно подобранный список фреймворков и библиотек Common Lisp.
  • Common Lisp Cookbook , совместный проект.
  • CLiki , Вики для бесплатно и с открытым исходным кодом системы Common Lisp работает на Unix-подобных системах.
  • Одним из основных репозиториев бесплатного Common Lisp для программного обеспечения является Common-Lisp.net .
  • На lisp-lang.org есть документация и демонстрация историй успеха.
  • Обзор истории Common Lisp: «История» . Common Lisp HyperSpec .
  • Краткий справочник Common Lisp - краткий обзор стандартного языка Common Lisp.
  • Planet Lisp Статьи о Common Lisp.
  • Quickdocs обобщает документацию и информацию о зависимостях для многих проектов Quicklisp.