Как стать автором
Обновить

Разработка web-приложений на языке Common Lisp (часть вторая)

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

Вторая часть этого обзора будет посвящена базовому конфигурированию Lisp-среды. Будет описана установка простой Lisp-системы. Кроме того, вкратце рассмотрим систему управления зависимостями ASDF.
image

Прежде чем двигаться дальше, нам потребуется настроить простую 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. Несмотря на эти расширения, я бы рекомендовал на первых порах ими не пользоваться и инсталлировать зависимости вручную. Это позволит хорошо понять внутренние связи в используемых библиотеках.
Теги:
Хабы:
+34
Комментарии29

Публикации