八発白中

技術ブログ、改め雑記

Common Lispとリアル・ワールドを繋ぐ「Roswell」の紹介

Roswell」というプロダクトがある。

clfreaksPodcastで聴いたことがあるかもしれないし、数週間前にLisp Meet Upで佐野さん (@snmsts) の発表を聞いたかもしれない。

知名度の割には意外と長く開発が続いているプロダクトだ。プロジェクトの最初のコミットが2014年7月30日なので、もう11ヶ月ほど開発が継続していることになる。開発は未だ活発で、バグ報告をするとその日のうちに修正がmasterに入ることが多い。

僕が働いてるサムライト株式会社では、個人の開発マシンではもちろん、アプリケーションサーバでも日常的に使われている。

RoswellにはChefのrecipeも既にある。

先日RoswellはTravis CIとCircle CI用のインストーラスクリプトも提供し始めた。これにより、CIサービスでRoswellを使ってCommon Lispプロダクトを継続テストできるようになった。

さらに、Common Lispのいくつかのプロダクト――Clack、Qlot、Woo――はRoswellユーザ向けに便利なスクリプトを提供している。

このようにRoswellの適用範囲は増えていく一方だ。

人々の声

f:id:nitro_idiot:20150611091538p:plain

Roswellはじわじわと現実世界に染み込んでおり、もはやこれなしで開発することは苦痛でしかないと感じる。

しかし、この温度感はclfreaksのメンバー以外にはまったく伝わってないと思う。それは佐野さんの控えめなマーケティング戦略のせいかもしれないが *1、それだけでなく、Roswellがあまりに急速に我々の間に広まって当たり前になってしまったために、あえて今更言及するほどでもない存在になってしまったからでもある。

この記事では改めてRoswellというプロダクトの紹介をする。

Roswellのインストール

Mac OS XならHomebrewで簡単にインストールできる。

$ brew tap snmsts/roswell
$ brew install roswell

その他のOSはREADMEを参照。

Roswellをインストールするとバイナリ版SBCLとQuicklispがインストールされる。

Common LispインストーラとしてのRoswell

RoswellはCommon Lisp処理系のインストーラとして開発が始まった。RubyのRVMやrbenv、PerlのPerlbrewなどを想像するとわかりやすい。

$ ros install sbcl
$ ros install sbcl/1.1.8  # バージョン指定
$ ros install ccl-bin     # Clozure CL

CIMと違ってSBCLとClozure CLにしか対応していないが、手広くない分この二つの処理系では問題なく動くことが期待できる。

インストールされた処理系、バージョンは切替ができ、rosで起動されるCommon Lispを変更できる。

$ ros run -- --version
SBCL 1.2.12

$ ros use sbcl/1.1.8

$ ros run -- --version
SBCL 1.1.8
$ ros run
* (+ 1 2)
3
* (lisp-implementation-type)
"SBCL"
* (lisp-implementation-version)
"1.1.8"

インストールされているLispros list installedで確認できる。

$ ros list installed
detail shown by
ros list installed [implemntation]

implementations:
    ccl-bin
    sbcl-bin
    sbcl/1.1.8
    sbcl

RoswellがCommon Lispとシェルを繋ぐ

Common Lispインストーラというだけなら環境構築を楽にしてくれるツールというだけで話は終わる。

しかし、Roswellは意図せず二弾式ロケットのようになった。その二弾目の機能が「シェルとの連携」だ。

今までCommon Lispでポータブルなスクリプトを書くのは難しかった。処理系によってコマンドライン引数が異なるからだ。

$ sbcl --load script.lisp --eval '(sb-ext:exit)'
$ ccl --load script.lisp --eval '(quit)'
$ clisp script.lisp

これに対しRoswellではrosというコマンドでラップされており、どの処理系も同じように扱える。

$ ros -l script.lisp

Roswell Script

これだけではない。.lispのようなファイルではなく、シェルコマンドとしてCLであることを意識せずに使えるスクリプトも書くことができる。

ros init [スクリプト名]を実行するとスクリプトのひな形が生成される。

$ ros init hoge
Successfully generated: hoge.ros

この中身はこのようになっている *2

$ cat hoge.ros
#!/bin/sh
#|-*- mode:lisp -*-|#
#|
exec ros -Q -- $0 "$@"
|#
(defun main (&rest argv)
  (declare (ignorable argv)))

この「.ros」という拡張子のついたスクリプトは「Roswell Script」と呼ばれており、既にいくつかのプロダクトで使われている。

Clackはサーバ起動スクリプトとして「clackup」を、Qlot *3 はラッパースクリプトqlot」を、Wooは自身の実行可能ファイルインストーラinstall-woo」を提供している。

これにより、Common Lispスクリプトを配布するときの手間がかなり省けることになる。単にRoswellをインストールしてください、で説明は終わる。

このRoswellの副次的な機能はShellyを殺しつつある。僕はこの変化を歓迎している。サムライトではShellyを使っていないし、今後移行する予定もない。Roswellを使おう。

まとめ

Roswellはインフラだ。今まで不可能だったことを可能にするようなプロダクトではないが、我々の生活をより良いものにしてくれる。いずれは入門書のセットアップに必ず出てきて「常識」と呼ばれるようになるだろう。

*1:Roswellの現在のバージョン番号は0.0.2.33。いつになったらバージョン1.0を迎えるのか。

*2:shebang行が #!/bin/sh だが、exec rosによりrosコマンドに入れ替わる。このハックの詳細は「割と処理系ポータブルなCommon Lisp実行可能ファイルを作る」で解説されている。

*3:プロジェクトローカルにQuicklispをインストールするツールhttps://github.com/fukamachi/qlot