Common Lisp

Материал из Википедии — свободной энциклопедии
Перейти к: навигация, поиск
Common Lisp
Семантика:

мультипарадигмальный: объектно-ориентированный, функциональный, императивный, метаязык

Класс языка:

язык программирования

Тип исполнения:

компилируемый

Появился в:

1984, стандартизирован ANSI в 1994

Автор:

комитет X3J13

Система типов:

сильная, динамическая, с опциональными декларациями типов

Основные реализации:

Allegro Common Lisp, ABCL, CLISP, Clozure CL, CMUCL, Corman Common Lisp, ECL, LispWorks, Scieneer CL, SBCL

Испытал влияние:

Lisp, Lisp Machine Lisp, MacLisp, InterLisp, Scheme

Повлиял на:

Clojure, Factor, Dylan, EuLisp, ISLisp, SKILL, Stella, SubL

Common Lisp (сокр. CL) — диалект языка Лисп, стандартизированный ANSI[1]. Был разработан с целью объединения разрозненных на тот момент диалектов Лиспа. Доступно несколько реализаций Common Lisp, как коммерческих, так и свободно распространяемых.

Common Lisp — мультипарадигменный язык программирования общего назначения. Он поддерживает комбинацию процедурного, функционального и объектно-ориентированного программирования.

Common Lisp включает в себя CLOS; систему Lisp макросов, позволяющую вводить в язык новые синтаксические конструкции, использовать техники метапрограммирования и обобщённого программирования.

История[править | править вики-текст]

После предложения управляющего из ARPA Боба Энгельмора разработать единый общий стандарт Лисп диалекта, началась работа над Common Lisp'ом в 1981 году. Многое в первоначальной структуре языка было разработано посредством связи через электронные письма. Первый обзор Common Lisp'а был произведён Гайем Льюисом Стилом на ACM симпозиуме по Лиспу и функциональному программированию 1982 года.

Первая документация по языку была опубликована в 1984 году как «Язык Common Lisp, первая редакция». Вторая редакция, выпущенная в 1990 году, включала много изменений, произведённых ANSI над языком в процессе стандартизации. Конечную же редакцию стандарта опубликовали в 1994 году.

С тех пор никаких обновлений стандарта выпущено не было, а различные расширения и улучшения Common Lisp'а (Unicode, параллелизм, основанные на CLOS ввод и вывод) обеспечиваются реализацией и библиотеками (многие доступны посредством Quicklisp)

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

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

(+ 2 2)                       ; складывает 2 и 2, возвращая результат 4. 
(- 8 3)                       ; вычитает из восьми три, возвращая результат 5. 
(reverse "Здравствуй, мир!")  ; переворачивает строку, возвращая «"!рим ,йувтсвардЗ"»

;; определения переменных и функций:
(defvar *x*)                  ; Определяет переменную *x*, не присваивая ей какого-либо
                              ; значения. Две звёздочки, являющиеся частью имени — принятый 
                              ; стандарт для именования глобальных переменных.

(setf *x* 42.1)               ; присваивает переменной *x* значение с плавающей запятой 42,1.

(defun square (x)             ; Определение функции square, получающей один аргумент
  (* x x))                    ; и возвращающей его квадрат.

(square *x*)                  ; вызывает функцию square, передавая ей значение переменной *x*
                              ; и возвращает её квадрат (1772,41).

(let ((a 3)(b 4)) (+ a b))    ; Функция let создаёт локальные переменные, присваивает им значения
                              ; (в данном случае переменной a присваивается значение 3, а b - 4), 
                              ; после чего вычисляет и возвращает результат функции
                              ; (в данном случае 7). Переменные локальны, следовательно
                              ; попытка посчитать значение (+ a b) вне тела let приведёт к ошибке.

Типы данных[править | править вики-текст]

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

Числовые типы включают в себя целые, дроби, числа с плавающей запятой и комплексные числа.[2] Common Lisp даёт возможность использовать большие числа для представления любых величин с большей точностью.

Литеры в Common Lisp не ограничены ASCII. Большинство современных реализаций поддерживают Юникод.

Понятие Символа довольно близко Лиспу, хотя, практически неизвестно в таком виде в других языках. В Лиспе символ — это уникальный объект из данных, включающих в себя: имя, значение, функцию, список свойств и пакет (пространство имён). Символы в Лиспе часто используются так же, как идентификаторы в других языках: для хранения значения переменной. Однако, у них есть множество других применений. Обычно, когда символу присваивается значение, оно тут же им и возвращается. Некоторые символы присваивают значение сами себе, так, например, булевы значения представлены в качестве двух самоопределяющихся символов, — T и NIL.

Есть несколько функций для округления скалярных типов разными способами. Функция round округляет аргумент до ближайшего целого числа, а если число стоит «посередине», то до ближайшего чётного. Функция truncate округляет числа по направлению к нулю. Функции floor («пол») и ceiling («потолок») округляют к ближайшему меньшему и ближайшему большему числу соответственно. Все функции возвращают дробную часть в качестве вторичного результата.

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

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

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

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

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

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

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

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

Функции[править | править вики-текст]

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

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

 ;; Сортирует список, используя функции > и <.
 (sort (list 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 #'first)   ; возвращает ((3 B) (4 C) (9 A))

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

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

 (defun square (x)
   (* x x))

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

 (defun square (x)
   "Calculates the square of the single-float x."
   (declare (single-float x) (optimize (speed 3) (debug 0) (safety 1)))
   (the single-float (* x x)))

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

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

 (flet ((square (x)
          (* x x)))
   (square 3))

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

Реализации[править | править вики-текст]

Common Lisp отличается от таких языков, как C#, Java, Perl, Python тем, что он определяется своим стандартом и не существует его единственной или канонической реализации. Любой желающий может ознакомиться со стандартом и создать свою собственную реализацию. Common Lisp автоматически признаёт эти типы как равные.[3]

Таблица сравнения основных реализаций[4][5]
Название Поддерживаемые платформы Компиляция Возможности Лицензия
CLISP[6] Windows, Mac, *nix Байт-код, JIT Маленький размер образа лисп-системы. Очень эффективная длинная целочисленная арифметика. Возможность создания исполняемых файлов. FFI(интерфейс для вызова низкоуровневых функций(функций из библиотек, написанных на Си и т. п.) и для оперирования «неуправляемой» памятью). Функции обратного вызова(интеграция с «родным» кодом платформы). GNU GPL
CMUCL[7] Linux, FreeBSD, Solaris, Darwin Байт-код, машинный код Высококачественный компилятор в машинный код. FFI. Функции обратного вызова(интеграция с «родным» кодом платформы). Общественное достояние с частями под BSD License
ECL Windows, *nix, Mac OS X Байт-код, машинный код через C Хорошая интеграция с программами на Си и с «родным» кодом платформы(FFI, функции обратного вызова, возможность создания «родных» для платформы динамических и статических библиотек). Возможность создания исполняемых файлов. «Родная» многопоточность на всех поддерживаемых платформах. GNU GPL с частями под другими лицензиями
Clozure CL (бывший OpenMCL)[8] Linux/PPC, Linux/X86-64, Darwin/PPC, Darwin/X86-64, FreeBSD/X86-64, Windows Машинный код Быстрый компилятор. Мощный и удобный FFI. Функции обратного вызова(интеграция с «родным» кодом платформы). Возможность создания исполняемых файлов. «Родная» многопоточность на всех поддерживаемых платформах. LGPL
SBCL[9] Linux, BSD, Solaris, Mac OS X (Darwin), Windows (экспериментально) Машинный код Высококачественный компилятор в машинный код. Возможность создания исполняемых файлов. FFI. Функции обратного вызова(интеграция с «родным» кодом платформы). «Родная» многопоточность на Linux, Solaris 10 и Mac OS X. Общественное достояние с частями под MIT License и BSD License
ABCL[10] JVM байт-код JVM Интерфейс к платформе Java. Многопоточность. Платформонезависимость. LGPL
Allegro Common Lisp[11] Windows, Unix, Linux, Mac OS X Машинный код http://franz.com/products/allegrocl/ Коммерческая, доступна ограниченная демоверсия
LispWorks[12] Windows, *nix, Mac OS X Машинный код Высококачественная IDE. CAPI — библиотека для создания пользовательского интерфейса. Хорошая интеграция с программами на Си и с «родным» кодом платформы(FFI, функции обратного вызова, возможность создания «родных» для платформы динамических и статических библиотек). Возможность создания исполняемых файлов. «Родная» многопоточность на всех поддерживаемых платформах. Полный список возможностей: http://www.lispworks.com/products/features.html Коммерческая, доступна ограниченная демоверсия
Corman Common Lisp Windows Машинный код http://www.cormanlisp.com/features.html С 2015 года — MIT License. Изначально распространялся как Shareware, с доступным исходным кодом системы (исключая IDE)

Примечания[править | править вики-текст]

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

Сообщества и форумы
Статьи
Документация и учебники