Roswell - Common Lisp environment setup Utility
Есть такой интересный проект, связанный с Common Lisp, как Roswell , который предназначен для установки и одновременного использования различных версий лиспа в систему. А так же интегрирован с quicklisp, несколько расширяя его возможности. Помимо прочего предоставляет возможность создания своих собственных скриптов на лиспе.
Использовать можно на целом ряде систем, в MacOS ставить очень просто:
$ brew install roswell
Есть пакет для Arch Linux, и предполагается подготовить для других дистрибутивов. Под Windows мне так и не удалось заставить его работать. Во всех остальных случаях предлагается устанавливать Roswell с помощью компиляции исходников.
По возможностям Roswell отправлять почитать официальную страницу. Довольно подробно описано все, что нужно. А сейчас хотел бы остановиться на некоторых проблемах.
Roswell особо привлекает к себе внимание из-за возможности создавать скрипты, в которых очень просто использовать quicklisp. SBCL в режиме скрипта данной возможности не имеет. Вроде все просто, создаем скрипт:
$ ros init script
$ cat script.ros
#!/bin/sh
#|-*- mode:lisp -*-|#
#| <Put a one-line description here>
exec ros -Q -- $0 "$@"
|#
(progn ;;init forms
(ros:ensure-asdf)
;;#+quicklisp (ql:quickload '() :silent t)
)
(defpackage :ros.script.script.3696842266
(:use :cl))
(in-package :ros.script.script.3696842266)
(defun main (&rest argv)
(declare (ignorable argv)))
;;; vim: set ft=lisp lisp:
Теперь достаточно прописать требуемые действия в функцию main
и все будет работать. При этом можно парсить аргументы командной строки, что передаются при запуске скрипта, и хранятся в переменной argv
. К примеру, чтобы вывести первый аргумент (без проверки на его существование), добавляем вызов одной команды:
(defun main (&rest argv)
(declare (ignorable argv))
(print (first argv)))
Теперь при запуске с передачей аргумента увидим ее значение:
$ ./script.ros 234
"234"
Вроде все замечательно и все хорошо. Но я попытался использовать roswell-скрипт Александра Артеменко, что он написал для запуска генератора статических сайтов coleslaw: coleslaw-cli . И сколько я не пытался, скрипт у меня ни разу нормально не отработал.
Для парсинга командной строки Александр использовал библиотеку clon
. Да, она очень удобна и функциональна, но подружить ее с Roswell мне так и не удалось. При запуске в режиме скрипта clon просто не отрабатывал. А вот если преобразовать скрипт в образ, то парсинг начинает нормально работать.
Хорошо, решил переписать скрипт, отказавшись от clon. В итоге получил следующее:
#!/bin/sh
#|-*- mode:lisp -*-|#
#| <Put a one-line description here>
exec ros -Q -- $0 "$@"
|#
(progn ;;init forms
(ros:ensure-asdf)
#+quicklisp (ql:quickload '("coleslaw") :silent t)
)
(defpackage :ros.script.col.3696839213
(:use :cl :coleslaw))
(in-package :ros.script.col.3696839213)
(defun main (&rest argv)
(declare (ignorable argv))
(if (< (length argv) 1)
(progn
(format t "Please fill directory")
(SB-EXT:EXIT))
(progn
(let ((directory (nth 0 argv)))
(format t directory)
(coleslaw:main directory)))))
И тут столкнулся очень интересной багой. По другому даже не знаю как назвать. Вызов coleslaw:main
приводит к запуску функции main
данного скрипта, что приводит к бесконечному выполнению.
Update: После того, как написал статью, Александр указал мне на мою ошибку. Как оказалось, после использования ql:quickload
не нужно было еще дополнительно прописывать coleslaw в секции use
. Убрал, все заработало. Более того, используя команду ros build col.ros
в короткий промежуток времени получил бинарник, который позволяет запускать coleslaw. Век живи, век учись…