четверг, 14 октября 2010 г.

SLIME на службе автоматизации

В предыдущем посте я рассказал как можно ускорить компиляцию шаблонов cl-closure-template и тем самым упростить процесс разработки. Кроме того, мне также досаждает другая проблема. Для перекомпиляции этих шаблонов я обычно переключаюсь в файл, в котором расположен код компилирующий шаблоны, ставлю курсов на этот код и нажимаю M-C-x. Другой вариант - оформить это в виде функции и вызывать через REPL. Оба способа достаточно не удобны и могут вызывать некоторое раздражение при активной правке шаблонов. Поэтому, для упрощения этой задачи я использую следующий приём (который можно использовать и для других подобных задач):

в конфигурационный файл Emacs (~/.emacs, ~/.emacs.d/init.el или т.п.) я добавляю такой код:
(global-set-key "\C-c\C-p" 
(lambda ()
(interactive)
(slime-eval-async '(mypackage:compile-all-templates)
(lambda (obj) (message "Compilation templates finished")))))
Теперь при нажатии в Emacs сочетания C-c C-p будет вызвана функция mypackage:compile-all-templates, которая вызывает перекомпиляцию шаблонов (или что либо другое, что нужно именно вам).

Ускоряем компиляции шаблонов cl-closure-template в SBCL

Система шаблонов cl-closure-template транслирует код шаблонов в код на CL и компилирует его в исполняемый, что на SBCL ведёт к генерации машинного кода и может занимать существенное время (поскольку SBCL очень медленный компилятор), например, по моему основному проекту пере-компиляция шаблонов занимает чуть более 12 секунда, что довольно сильно напрягает в процесс разработки. Мне бы хотелось, что бы в режиме разработки можно было бы значительно ускорить время компиляции шаблонов, пусть и за счёт снижения их производительности. Как оказалось, решить эту проблему для SBCL можно очень просто за счёт использования переменной sb-ext:*evaluator-mode*:
(defparameter *developer-mode* nil)

(let ((sb-ext:*evaluator-mode* (if *developer-mode* :interpret :compile)))
(closure-template:compile-template :common-lisp-backend ..))
Здесь, когда переменная *developer-mode* установлена в значение отличное от NIL, шаблоны не компилируются, а интерпретируются. Работают они после это, конечно, не так быстро, но в процессе разработки это и не так важно. В результате, время перекомпиляции шаблонов (в режиме разработки) в моём проекте сократилось до 0.6 секунды, т.е. уменьшилось примерно в 20 раз.

среда, 13 октября 2010 г.

ANSI Common Lisp на русском

Судя по всему, издательство Символ-Плюс начало подготовительные работы к выпуску ANSI Common Lisp на русском языке. Если эти планы осуществляться, то это будет фактически первое за 20 лет издание книги о CL на "великом и могучем". Будем ждать.

понедельник, 11 октября 2010 г.

mount-submodule

В RESTAS произошло важное переименование: макрос restas:define-submodule теперь называется restas:mount-submodule - такое имя более точно отражает суть данного макроса. Сейчас изменения доступны в git-версии. Следующий релиз, скорей всего, будет иметь версию 0.1.

среда, 6 октября 2010 г.

Конфликт имён

Я тут всёми силами готовлюсь к выпуску RESTAS-0.1 и под это дело (да с чужой подачи) заинтересовался запустить RESTAS под LispWorks. Вроде, проблем быть было не должно. Но вот засада - при попытке загрузить систему сразу ошибка. Проблема c моим пакетом garbage-pools - его nickname конфликтует с nickname пакета graphics-ports, который содержится в образе LispWorks.

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

В общем, найденное решение кажется мне достаточно тривиальным:
#+:lispworks (rename-package '#:graphics-ports '#:graphics-ports nil)
(asdf:operate 'asdf:load-op :restas)
#+:lispworks (rename-package '#:garbage-pools '#:garbage-pools)
#+:lispworks (rename-package '#:graphics-ports '#:graphics-ports '(:gp))
Т.е. до загрузки RESTAS удаляем nickanmes пакета graphics-ports, загружаем RESTAS, удаляем nicknames у пакета garbage-pools, восстанавливаем nicknames у пакета graphics-ports.

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

вторник, 5 октября 2010 г.

RESTAS-0.0.11

Выпустил новую версию RESTAS - 0.0.11.

Хотел бы немого пояснить принцип, по которому я определяю релизы. У меня есть, скажем так, основное приложение, надо которым я работаю в рабочее время и за которое мне платят деньги. Размещено оно на отдельном сервере под управлением Gentoo, установку основных lisp пакетов на нём я произвожу с помощью archimag-lisp-overlay. Разработку RESTAS я произвожу параллельно с разработкой этого приложения. Как только я задействую какие-то новые функции RESTAS в этом приложении и появляется необходимость обновить его на рабочем сервере, так сразу я делаю новый релиз, обновляю ebuild в оверлее и произвожу обновление нужных пакетов. Вот и вся логика ))

воскресенье, 3 октября 2010 г.

parse-route-url

Добавил в RESTAS, новую функцию:
(defun parse-route-url (url route-symbol &optional submodule-symbol)
...)
Поскольку польза от неё, как мне кажется, не вполне очевидна, то должен немного пояснить для чего я её использую.

Я широко использую REST-стиль, в том числе, для взаимодействия между JavaScript-клиентом и веб-сервером. При этом, все данные представляются как ресурсы и идентифицируются с помощью URL, а в качестве обменного формата используется JSON (можно и XML). Сейчас я столкнулся с тем, что часто необходимо с клиента (JavaScript) отправлять данные на сервер для какой-либо обработки, а в отсылаемых на сервер данных содержатся url-идентификаторы объектов. На сервере во время обработки необходимо разбирать эти url-индикаторы на составляющие их параметры (например, для составления запросов к базе). Делать это вручную (с помощью регулярных выражений) очень непродуктивно и совершенно не масштабируемо, поскольку формат этих url зависит от конфигурации среды и для их генерации используется функция restas:genurl. Таким образом, функция restas:parse-route-url является обратной к семейству функций genurl.

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