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

Прежде чем двигаться дальше, нам потребуется настроить простую Lisp-систему, необходимую для экспериментирования. Нижеприведённая инструкция по установке рассчитана на Debian Lenny, но, наверняка, будет работать во многих других дистрибутивах Linux (например, в Ubuntu).
Итак, для начала инсталлируем следующие пакеты: SBCL, Emacs и SLIME. SBCL – это компилятор Common Lisp, который мы обсуждали в первой части этого обзора. Emacs – текстовый редактор, в котором будем писать программный код. Я никогда не порекомендовал бы вам этот редактор, если бы не одно существенное обстоятельство. Именно для него написан SLIME, третий из вышеперечисленных пакетов. SLIME (Superior Lisp Interaction Mode for Emacs) – это клиент-серверная система для взаимодействия с Lisp. Клиентская часть, которая так и называется — SLIME, интегрируется с Emacs (являясь его модулем расширения). Серверная часть SLIME называется SWANK и непосредственно взаимодействует с Lisp. SLIME-клиент и SWANK связываются друг с другом посредством TCP, что даёт возможность удалённо управлять Lisp-системой.
После инсталляции этих трёх компонентов нужно познакомить их друг с другом. Для этого добавляем в конфигурационный файл ~/.emacs следующие строки:
Теперь мы можем смело запускать нашу Lisp-систему. Открываем Emacs, вводим M-x slime (новичкам в Emacs читать краткое руководство). Если всё прошло хорошо, то откроется REPL (Lisp-консоль). Введите что-то вроде
Slime позволяет вычислять текущие выражения, искать определения символов, форматировать код, делать контекстные подсказки и многое-многое другое. Удобство работы со SLIME становится неоспоримым в сравнении с работой голого SBCL в терминале. Позже, когда появится опыт работы с Emacs (для тех, у кого его не было ранее), можно будет тонко сконфигурировать интерфейс. Например, поменять цвет фона и текста, добавить поддержку юникода и прочее. Сейчас это не так важно, главное, что мы имеем простую Lisp-среду в которой уже можно работать.
Поскольку мы не можем написать всё с нуля, нам потребуются готовые сторонние библиотеки. Потому будет полезным разобраться со способом их дистрибуции. Большинство сторонних библиотек используют систему управления зависимостями ASDF, ставшую де-факто стандартом в мире Common Lisp. Нам не потребуется инсталлировать ASDF – она идёт в комплекте с SBCL.
Итак, что собой представляет ASDF? Эту систему можно сравнить с утилитой make в мире UNIX. Она отслеживает связи и зависимости между различными единицами кода (от единичного файла до большого фреймворка), координируя их компиляцию и загрузку. Большинство ASDF-совместимых библиотек имеют в корневой директории один asd-файл, описывающий программную систему (в терминологии ASDF). Любая сколько нибудь сложная система состоит из нескольких компонентов. Компонент может быть как модулем, т.е. контейнером для других компонентов, так и отдельным файлом. Компоненты зависят от других компонентов, а системы — от других систем. На основании этих и других данных ASDF определяет порядок компиляции и загрузки целевой системы.
Структура и связи системы описываются с помощью декларативного DSL (предметно ориентированного языка). Важнейшей частью этого DSL является директива defsystem. Приведу пример простого asd-файла:
Здесь первая строка содержит директиву переключения в пакет (аналог пространства имён в Common Lisp — здесь и далее слово «пакет» будет применяться в этом значении) ASDF. Это сделано для удобства, чтобы не мешать описание системы и код её реализации в одну кучу (в качестве альтернативы можно создать для этого новый пакет my-lib-asd). Далее определяется система my-lib, содержащая два модуля и зависящая от системы my-base-lib. Обычно каждый модуль соответствует директории с исходными файлами, объединёнными по некоторому структурному или функциональному признаку. В данном примере первый модуль называется “common” и содержит три файла: независимые “common-file-1” и “common-file-2” и зависимый от этих двух “common-file-3”. Второй модуль называется “main”, содержит единственный файл “main-file” и зависит от модуля “common”.
Чтобы загрузить систему “my-lib” нам потребуется ввести следующую команду:
Эта команда вначале проверит актуальность каждого из компонентов в каждой из систем (my-lib, my-base-lib и тех, от кого зависит последняя). Неактуальные компоненты будут перекомпилированы, актуальные – сразу загружены в память (т.е. их символы будут обработаны и добавлены в соответствующие пакеты). Если не все системы или компоненты, от которых зависит целевая система, будут найдены, то произойдёт ошибка загрузки.
Теперь разберёмся, откуда ASDF знает, где искать asd-файлы. При компиляции или загрузке системы ASDF просматривает список директорий, хранящийся в переменной asdf:*central-registry*, проверяя наличие требуемого asd-файла (его имя должно соответствовать имени целевой системы). Поэтому перед загрузкой новой системы можно добавить в этот список путь к её корневой директории. Более разумным подходом является выделение специальной директории, содержащей символьные ссылки на asd-файлы всех имеющихся систем. Для этой цели подойдёт директория /usr/share/common-lisp/systems/, путь к которой по умолчанию добавлен в asdf:*central-registry*.
Имея базовые знания о ASDF, мы уже можем пользоваться множеством сторонних библиотек, которые с избытком наличествуют в Интернете (здесь важнейшим путеводителем будет CLiki — крупнейший портал, посвящённый Common Lisp). Остаётся только один вопрос: как инсталлировать нужные библиотеки, автоматически отслеживая и скачивая их зависимости? ASDF располагает лишь базовой функциональностью, не позволяя автоматизировать процесс инсталляции. К счастью, есть достаточное количество ASDF-расширений, решающих эту задачу. К ним, в частности, можно отнести ASDF-INSTALL. Несмотря на эти расширения, я бы рекомендовал на первых порах ими не пользоваться и инсталлировать зависимости вручную. Это позволит хорошо понять внутренние связи в используемых библиотеках.
Вторая часть этого обзора будет посвящена базовому конфигурированию Lisp-среды. Будет описана установка простой Lisp-системы. Кроме того, вкратце рассмотрим систему управления зависимостями ASDF.

Прежде чем двигаться дальше, нам потребуется настроить простую Lisp-систему, необходимую для экспериментирования. Нижеприведённая инструкция по установке рассчитана на Debian Lenny, но, наверняка, будет работать во многих других дистрибутивах Linux (например, в Ubuntu).
Итак, для начала инсталлируем следующие пакеты: SBCL, Emacs и SLIME. SBCL – это компилятор Common Lisp, который мы обсуждали в первой части этого обзора. Emacs – текстовый редактор, в котором будем писать программный код. Я никогда не порекомендовал бы вам этот редактор, если бы не одно существенное обстоятельство. Именно для него написан SLIME, третий из вышеперечисленных пакетов. SLIME (Superior Lisp Interaction Mode for Emacs) – это клиент-серверная система для взаимодействия с Lisp. Клиентская часть, которая так и называется — SLIME, интегрируется с Emacs (являясь его модулем расширения). Серверная часть SLIME называется SWANK и непосредственно взаимодействует с Lisp. SLIME-клиент и SWANK связываются друг с другом посредством TCP, что даёт возможность удалённо управлять Lisp-системой.
После инсталляции этих трёх компонентов нужно познакомить их друг с другом. Для этого добавляем в конфигурационный файл ~/.emacs следующие строки:
(setq inferior-lisp-program "/usr/bin/sbcl") (require 'slime) (slime-setup)
Теперь мы можем смело запускать нашу Lisp-систему. Открываем Emacs, вводим M-x slime (новичкам в Emacs читать краткое руководство). Если всё прошло хорошо, то откроется REPL (Lisp-консоль). Введите что-то вроде
(+ 1 1)
для уверенности в том, что SBCL запущен и выполняет наши команды.Slime позволяет вычислять текущие выражения, искать определения символов, форматировать код, делать контекстные подсказки и многое-многое другое. Удобство работы со SLIME становится неоспоримым в сравнении с работой голого SBCL в терминале. Позже, когда появится опыт работы с Emacs (для тех, у кого его не было ранее), можно будет тонко сконфигурировать интерфейс. Например, поменять цвет фона и текста, добавить поддержку юникода и прочее. Сейчас это не так важно, главное, что мы имеем простую Lisp-среду в которой уже можно работать.
Поскольку мы не можем написать всё с нуля, нам потребуются готовые сторонние библиотеки. Потому будет полезным разобраться со способом их дистрибуции. Большинство сторонних библиотек используют систему управления зависимостями ASDF, ставшую де-факто стандартом в мире Common Lisp. Нам не потребуется инсталлировать ASDF – она идёт в комплекте с SBCL.
Итак, что собой представляет ASDF? Эту систему можно сравнить с утилитой make в мире UNIX. Она отслеживает связи и зависимости между различными единицами кода (от единичного файла до большого фреймворка), координируя их компиляцию и загрузку. Большинство ASDF-совместимых библиотек имеют в корневой директории один asd-файл, описывающий программную систему (в терминологии ASDF). Любая сколько нибудь сложная система состоит из нескольких компонентов. Компонент может быть как модулем, т.е. контейнером для других компонентов, так и отдельным файлом. Компоненты зависят от других компонентов, а системы — от других систем. На основании этих и других данных ASDF определяет порядок компиляции и загрузки целевой системы.
Структура и связи системы описываются с помощью декларативного DSL (предметно ориентированного языка). Важнейшей частью этого DSL является директива defsystem. Приведу пример простого asd-файла:
(in-package :asdf)
(defsystem my-lib :name "my-lib" :version "0.1" :components (
(:module "common" :components (
(:file "common-file-1")
(:file "common-file-2")
(:file "common-file-3" :depends-on ("common-file-1" "common-file-2"))))
(:module "main" :components (
(:file "main-file")) :depends-on (:common)))
:depends-on (:my-base-lib))
Здесь первая строка содержит директиву переключения в пакет (аналог пространства имён в Common Lisp — здесь и далее слово «пакет» будет применяться в этом значении) ASDF. Это сделано для удобства, чтобы не мешать описание системы и код её реализации в одну кучу (в качестве альтернативы можно создать для этого новый пакет my-lib-asd). Далее определяется система my-lib, содержащая два модуля и зависящая от системы my-base-lib. Обычно каждый модуль соответствует директории с исходными файлами, объединёнными по некоторому структурному или функциональному признаку. В данном примере первый модуль называется “common” и содержит три файла: независимые “common-file-1” и “common-file-2” и зависимый от этих двух “common-file-3”. Второй модуль называется “main”, содержит единственный файл “main-file” и зависит от модуля “common”.
Чтобы загрузить систему “my-lib” нам потребуется ввести следующую команду:
(asdf:oos ‘asdf:load-op :my-lib)
Эта команда вначале проверит актуальность каждого из компонентов в каждой из систем (my-lib, my-base-lib и тех, от кого зависит последняя). Неактуальные компоненты будут перекомпилированы, актуальные – сразу загружены в память (т.е. их символы будут обработаны и добавлены в соответствующие пакеты). Если не все системы или компоненты, от которых зависит целевая система, будут найдены, то произойдёт ошибка загрузки.
Теперь разберёмся, откуда ASDF знает, где искать asd-файлы. При компиляции или загрузке системы ASDF просматривает список директорий, хранящийся в переменной asdf:*central-registry*, проверяя наличие требуемого asd-файла (его имя должно соответствовать имени целевой системы). Поэтому перед загрузкой новой системы можно добавить в этот список путь к её корневой директории. Более разумным подходом является выделение специальной директории, содержащей символьные ссылки на asd-файлы всех имеющихся систем. Для этой цели подойдёт директория /usr/share/common-lisp/systems/, путь к которой по умолчанию добавлен в asdf:*central-registry*.
Имея базовые знания о ASDF, мы уже можем пользоваться множеством сторонних библиотек, которые с избытком наличествуют в Интернете (здесь важнейшим путеводителем будет CLiki — крупнейший портал, посвящённый Common Lisp). Остаётся только один вопрос: как инсталлировать нужные библиотеки, автоматически отслеживая и скачивая их зависимости? ASDF располагает лишь базовой функциональностью, не позволяя автоматизировать процесс инсталляции. К счастью, есть достаточное количество ASDF-расширений, решающих эту задачу. К ним, в частности, можно отнести ASDF-INSTALL. Несмотря на эти расширения, я бы рекомендовал на первых порах ими не пользоваться и инсталлировать зависимости вручную. Это позволит хорошо понять внутренние связи в используемых библиотеках.