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

    Данный обзор является небольшим путеводителем для тех, решился (или решается) доверить этому чудесному языку будущее своего стартапа. Несмотря на то, что основной акцент будет ставиться на 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. Несмотря на эти расширения, я бы рекомендовал на первых порах ими не пользоваться и инсталлировать зависимости вручную. Это позволит хорошо понять внутренние связи в используемых библиотеках.

    Similar posts

    Ads
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More

    Comments 29

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

      PS: Для тех, кто только начинает изучать лисп, могу посоветовать эту статью: www.cs.sfu.ca/CC/310/pwfong/Lisp/1/tutorial1.html — в ней кратко изложены самые основы. Все понятно и с примерами.
        +2
        Простите за небольшие порции, просто сейчас завален работой — времени вообще нету… но следующая часть будет посвещена web-серверу Hunchentoot — там должно быть больше раза в полтора. К тому же боюсь, что объёмами и сложностью отпугну массы.
          +2
          Отлично, будем ждать. Да, большие статьи читает скорее всего меньше человек, но тут и тема весьма специфична. Кому это интересно, тот прочтет и большую статью.

          Большое вам спасибо за ваши статьи.
            0
            Спасибо за хорошие слова.
        +2
        а вы используете фреймворки для веб-приложений на лиспе? и существуют ли они
          +1
          Да, существуют. Я вам сходу могу назвать RESTAS, например restas.lisper.ru
          Остальные, конечно, надо поискать.
            0
            Пытался использовать Weblocks. Не пошло. Главная причина моего отказа от этого фрейворка в том, что он некорректно работает IE6 и IE7. Для серьёзного проекта это не годитсяю. Плюс свою роль сыграла моя неопытность в программировании под Web — хотел ковыраться на более низком уровне, чтобы ручками всё попробовать.
            –10
            Нде… Извращение извращения=)
            • UFO just landed and posted this here
                +5
                Лисп — это не извращение ;)
                  –9
                  Лисп — это недоразумение =)
                    +3
                    Сравнение зарплат как бы говорит об обратном.
                      –3
                      олололо=)

                      Это ужасно, когда количество вакансии в мире можно пересчитать на пальцах=) Конкуренция етпи…

                    • UFO just landed and posted this here
                        –2
                        Нет чувак! Недоразумение у тебя в штанах =)
                        • UFO just landed and posted this here
                            –1
                            Ну если что то со вчера изменилось!

                            А так о ужас!
                  +2
                  Блин, открывал статью с мыслью «Ура, наконец-то прелюдии кончились и начали рассказывать про веб-разработку!». Однако, нет.
                  Присоединяюсь к коменту выше про чаще и больше.

                  Если уж начали делится ссылками на книжки

                  pcl.catap.ru/ — перевод очень хорошей книги по CL, сам по ней учусь
                  вот этой вот www.gigamonkeys.com/book/
                  www.paulgraham.com/onlisptext.html еще
                  и еще есть Мир лиспа в двух томах

                  думаю, во всем цикле статей можно будет собрать из каментов полный список учебной литературы по CL =)
                    0
                    Да, Practical Common Lisp — лучшая книга по Common Lisp из тех, что мне встречались.
                      +1
                      я очень заинтересовался ФП в веб-программировании, вот кто бы описал для каких проектов лучше использовать функциональные языки програмирования. Читал про erlang думаю для серверных частей онлайн-игр как раз подойдет, ну и вообще где есть comet. Просто хочется знать какие плюсы даст использование лиспа или другого ФЯП.
                        0
                        Присоединяюсь, самого давно мучает этот вопрос. Какой «профит» от изучения lisp — просто еще один вариант инструмента, или это действительно дает какие-то явные преимущества?
                          +1
                          Ответ здесь: <a href='http://lisper.ru/pcl/introduction-why-lisp'Почему Lisp?
                            0
                            Уточню. Ответ «Если вы считаете, что величайшее удовольствие в программировании доставляет код, делающий многое и выражающий ваши желания просто и ясно, тогда программирование на Common Lisp вероятно будет самым приятным из того, что можно сделать на компьютере» мне не подходит. Я считаю что проще всего мне писать в достаточно привычном C-подобном синтаксисе — для веба это Java. Есть ли в lisp какой-то прирост эффективности — типа «быстрее что-то обрабатывает», или что-то такое? Или это просто «круто и очень удобно»?
                              +1
                              Если вы не готовы отказаться от С-подобного синтаксиса, тогда вам ничего не надо кроме языков с таким вот синтаксисом.

                              Если кратко, то преимущество Lisp можно охарактеризовать следующим образом. В процессе решения сколько нибудь нетривиальной задачи мы строим DSL, а лишь потом с его помощью её решаем. Так вот Lisp (не только Common, но и другие языки со скобочным синтаксисом) позволяет строить максимально высокоуровневый DSL с минимумом усилий. Т.е. язык, позволяющий достигать заданной степени абстракции при намного меньшей сложности и объёме кодирования, в сравнении с мэйнстрим-языками.
                                0
                                Спасибо!
                          0
                          Читал про erlang думаю для серверных частей онлайн-игр как раз подойдет

                          Да ни разу он не подойдет.
                            0
                            Среди лиспов есть и более-менее функциональные ( racket-lang.org ), но Common Lisp, о котором пишет ababo имеет очень ограниченную реализацию функциональной парадигмы. Есть замыкания и функции высших порядков, но в стандарте не описана оптимизация хвостовых вызовов. Большинство реализаций её делает, но писать рекурсивные реализации алгоритмов — не лучшая идея.

                            С точки зрения многопоточности преимущества появляются именно от полного отказа от императивщины. Поэтому вы здесь очень точно на след erlang'а напали. :) Ну или можно самому контролировать и поддерживать функциональный стиль на CL и выбирать реализации, выполняющие TCO.
                              0
                              Основные реализации Common Lisp например SBCL поддерживают TCO
                            0
                            книги по Лиспу www.monocle.info/faq/#lisp

                            Only users with full accounts can post comments. Log in, please.