読者です 読者をやめる 読者になる 読者になる

八発白中

はてなブログに引越しました。

Lisperはプログラムに何を見るか

男子校に通う中学生の僕らにとって「家庭科」の授業は休憩時間のようなものだった。

僕の中学校には家庭科室というものがない。だから、いつもの教室で野菜の種類やそれに含まれる栄養素なんかを教わるというだけの、正直退屈な授業だった。話される内容はどれもただ暗記すればいいものなので、授業を聴かなくても定期試験前に教科書を読み通すだけで九〇点は取れる教科だった。

学校としても文科省の教育課程に沿うがためだけに時間割にねじ込んでいるに過ぎなかったと思う。特別教室がないことでも真面目にこの教科を取り扱う気がないことがわかるし、生徒の方でもその学校の態度を敏感に感じとっていた。

そんなやる気のない男子学生の前に立って話すのは教師にとって楽しいものではなかっただろう。僕らの先生は、落ち着いた雰囲気でどこかしたたかさのある、髪の長い女の先生だった。

その日も彼女はいつも通り、キノコに含まれる何々という栄養素が、体内でビタミンDになるという話をしていた。ふてぶてしくも一人のクラスメイトが先生に訊ねた。「こんなこと覚えて意味あるんですか」

すると先生は一瞬黙り込んでから視線を手元の教科書に落としたままひとりごとのように答えた。「意味のない知識が多いほど、人生は面白いの」

先生はそれ以上は言葉を加えず、再び何々という栄養素に話を戻した。

最初、僕は先生の言葉の意味を単純に知識欲を満たすことができるからだと思った。けれど、彼女が本当に言いたかったことは、もっと深い。知っているのと知らないのとでは、ものの感じ方が違う。同じものを見ていても見ているものが違うんだ。

知っている花が多ければ散歩中に見つけた花で季節を感じることができる。歴史を知らない人にとって関ヶ原はただの荒野でしかないけれど、知識があればそこに武者たちの壮大な物語も見ることができる。

彼女の授業で今でも覚えていることと言えば、レモンが評判ほどにはビタミンCを含まないという程度のことだけど、その日の彼女のその言葉だけは今でも鮮明に覚えている。

自分にしか見えないもの

逆に、自分には見えていて他人には見えていないものもある。

最近、妻がプログラミングの勉強を始めた。彼女は都内のWeb企業に勤めてはいるがプログラマではなく、仕事上求められるわけではない。ただ単純にプログラミングはどういったものか、何ができるのか、ということを知りたいという純粋な好奇心から学ぶことを始めたようだ。

最初に学ぶプログラミング言語は何がいいかな、と彼女は訊いた。僕は、JavaScriptが良いだろうね、と答えた。特別難しい言語ではないし、ブラウザという身近な処理系がある。何より学べば何かしら役にも立つかもしれない。

けれど、入門書という面ではこの言語は恵まれない。僕自身、良いと思ったJavaScriptの本は2冊しかない。そのうちの一つの「JavaScript 第5版」が家にあったので妻に与えてみたが、ほんの数章で読むのをやめてしまった。

それから僕と彼女は池袋のジュンク堂に行って、技術書コーナーを行ったり来たりすることになった。さまざまな言語の入門書をめくってみて彼女に最適なものを一緒に探した。

ある本は難しすぎ、ある本は内容が浅すぎた。これは、と思う本を手にとって彼女に意見を求めてみても、内容が難しい、と言われる。良い本かどうかの判断はできるが、何を難しいと思うのかは僕にはわからない。

最終的に選んだのは「初めてのPerl 第6版」だった。この本は僕が最初にプログラムを学んだ本でもあり、文章も面白くて読み進められる工夫がされている。他の言語を後に学ぶにしても、最初はPerlで入門してからなら理解も深まるかもしれない。

プログラミング学習の難しさ

僕のことを知る人は、僕の妻がCommon LispではなくPerlを学んでいると聞いて不思議に思うようだ。

自分の妻にCommon Lispを勧めない理由の一つは、彼女がその恩恵を受けるほど複雑な問題を解いたり、ある程度の規模のプログラムを書くという機会はないだろうという推測からだが、他にもCommon Lispを学ぶのは他の言語に比べて全く簡単ではないだろうという考えからでもある。

Lispは構文上のルールが少ないので、学ぶのが簡単だと言う人もいる。僕自身も少し前までそう考えていた。けれど、学習の容易さは覚えるべき文法ルールの多少によるものじゃない。プログラミング言語の習得の難しさは、その言語が提供する抽象化の概念の理解の難しさに比例する。

プログラミング言語はもともとコンピュータを抽象化する目的で作られた。人間が0と1の組み合わせでプログラムを書かなくてもいいようにアセンブリ言語ができたわけだし、さらに高等な命令を持つCのような言語も流行した。プログラミング言語の進化は概ね、より人間に優しい言葉になる進化だ。

その後、プログラミング言語はもっと高度な抽象化によってプログラムを簡単に書けるように進化した。それによって決して単純ではなくなるが、一度学ぶと簡単にプログラムを書けるようになるといった類の改善だ。オブジェクト指向がその一例だろう。Cがアセンブリ言語に対して行う抽象化とは違い、オブジェクト指向は非連続な言語の進化だ。オブジェクト指向の概念は、明らかにCのfor文より高度な抽象化だ。

進歩したプログラミング言語ほど、このような抽象化された概念が多い。――レキシカルクロージャ再帰関数、Cのポインタ、Perlのコンテキスト、Schemeの継続。そして、高度な概念を扱う言語ほど学ぶのが難しい。

その中でもLispは学ぶのが難しい部類だと僕は思う。事実、プログラミングの全くの初心者だけでなく、他の言語で十分な経験がある人でもLispを前に容易に降参するのを見た。僕自身、Schemeを学ぶ段階でPerlPHPJavaScriptの経験があったけれど、他の言語を習得するのに比べて多くの苦痛が伴った。Lispを学ぶことを困難にしているものは何だろうか?

この問いは、本にかじりついて学ぶ過程をくぐり抜けた僕にとっては無用ではあるけれど、今後Lispを学ぼうという人が挫折するだろう石ころを事前に取り除けるというならそれに越したことはない。何しろ僕には、いずれ妻にCommon Lispを教えなければならない日が来るかもしれないのだから、今のうちに考えておきたい。

Lispは今まで多くの言語に影響を与えてきたため、Lispが持つ多くの概念は他の言語の習得者にとって既に真新しいものではなくなっているはずだ。代表格と言える無名関数はもはやほぼすべての高級言語に含まれている。けれど、他の言語が真似できない、最もLispの中で重要な概念をそのカッコに隠している。Lispではそれを「マクロ」と呼ぶ。

マクロ: プログラム可能なプログラム

Lisp is a #1=(programmable . #1#) programming language.

マクロはプログラムを書くプログラムである。

人によってはこれを聞いただけで恐怖心を感じて考えるのをやめてしまう。そんなものいつ必要になるんだ? ――ほとんどいつでも。ただ、ここではその議論に立ち入るのをやめよう。深呼吸して、ただここではLispにそういった機構があるという事実だけを知っていればいい。

通常のプログラミング言語では、実行されるコードをプログラムに記述する。これを一層目のプログラムだとしよう。Lispではさらにその一層目のプログラムを生成する二層目のプログラムを書くことができる。このようなプログラムはメタプログラムと呼ばれる。

Lispが異常な点は、そのメタプログラムをユーザが自由に書けるところだ。メタプログラム内ではフルのLispの機能が使える。もちろん自分で定義した関数を使うこともできるし、ライブラリも使える*1。こういうプログラムが欲しい、と書けば、書くべきプログラムをLispが代わりに書いてくれる。

そしてこの層の連鎖は無限に続けることができる。つまり、プログラムを書くプログラムを書くプログラムを書くプログラムを書くこともできる*2Lispはプログラム可能なプログラミング言語なのだ。

なぜLispプログラマにとってマクロはそれほど重要なのか? それは単にマクロが提供する文法上の便利さなどではなく、マクロがプログラムを操作するプログラムであり、それがLispコミュニティの中心的テーマであり続けているからだ。FORTRANが数を、Cが文字とポインタをこき使う言語ならば、Lispはプログラムをこき使う言語なのだ。

Why are macros so important to Lisp programmers? Not merely for the syntactic convenience they provide, but because they are programs that manipulate programs, which has always been a central theme in the Lisp community. If FORTRAN is the language that pushes numbers around, and C is the language that pushes characters and pointers around, then Lisp is the language that pushes programs around.

Quoted from 「The Evolution of Lisp」by Guy L. Steele Jr. & Richard P. Gabriel

マクロを持つために必要なもの

何も僕は、Lispを学ぶならまずはマクロを学ばないといけないなんてひねくれたことを考えているわけじゃない。僕が思うのは、Lispにはマクロがあるからこそ他の言語にはない高度な抽象化を行っているために、それがLispを理解する妨げになっているんじゃないか、ということだ。

Lisp はより妥協の少ない哲学をもっていて、非常に強力でよく統制のとれた 言語の核を提供している。このことは Lisp を学ぶのをむずかしくしている。 なぜなら最初から高水準の抽象化を扱わければならず、見た目や感覚に 頼らずに自分がいま何をしているかを理解しなければならないからだ。

Quoted from「LispプログラマのためのPython入門」by Peter Norvig

じゃあ、Lispが提供する高度な抽象化とは何か。

一般に「Lisp」と呼ばれている言語の特徴は「プログラムをその言語自身の平易なデータ構造で表すことができる」ことだ*3

この特徴は「マクロ」と無関係ではない。プログラムを生成するプログラムを書くためには、プログラム自身がプログラムから扱いやすいものでなければならないからだ。

Lisp方言の一つであるCommon LispのコードはCommon Lisp自身の平易なデータ構造で表せる。式は「リスト」で表されるし、変数は「シンボル」というデータ型で表される。他の言語で変数を表す「変数型」のようなものがないことを考えても、やはりLispは特異だと言える。

自然、Lispプログラムには、「プログラミング言語としてのLisp」と、「メタプログラミング言語としてのLisp」が混在することになる。プログラマは、プログラム中のそれぞれの部位がどのタイミングで評価 (evaluation) されるかを意識しながらプログラムを書く。この制御にはクォートを使う。これも、マクロを実現するためのLisp特有の機能だ。評価する機能 (eval) はありふれていても、評価を抑制する機能がある言語が他にあるだろうか。

熟練のLisperたちは日常的に入れ子になった式の評価タイミングを意識して、息を吸うようにクォートを使いこなす。Lispを知らない人にとって平坦に見えるプログラムも、Lisperにとっては確かな立体感を持って知覚される。

おわりに

あの日家庭科の授業で生徒が正直過ぎる無礼さで質問をぶつけたとき、先生はこう言うこともできたはずだ。将来一人暮らしをしたときに自炊をしなければならないでしょう。そのとき自分の栄養管理をするのはあなた自身なのよ。けれど、そんな説教くさい話では生意気な男子中学生の態度を改めさせることなどできなかったに違いない。

Lispは学ぶべき言語だろうか。僕も説教くさい話はやめよう。Lispは楽しい。それを共感できる人間は、多いほうがいいけれど。


この記事の下書きを読んで意見をくれた同僚のRudolph MillerMasayuki Takagi@yanqirenshi、そして妻の@meymaoに感謝します。

*1:この利点を示すわかりやすい例として、プログラムを生成するときにハッシュテーブルを使って効率的なプログラムを生成するようなメタプログラムを書いたりできる。このアイデアは僕の書いた高速なHTTPパーサ「fast-http」で実際に使われている。

*2:これは必ずしも連続したプロセスである必要はない。Common Lispではコンパイル時に実行することもできるし、実行時にコンパイルすることもできる。

*3:最初期のevalを持たないLISPは完全なLisp実装ではない。現代の感覚で言えば最初期のLISPFORTRANのリスト操作ライブラリと言ったほうが正確なものだったろう。また、敢えて「平易な」と入れているのは誰かが「◯◯の言語でも構文木をデータとして扱うことができる」と言い出すのを見越してのことだ。Lispの場合プログラムはリストというポピュラーなデータ構造で扱える。これはコンパイル時にもそのプログラムに対して標準のリスト処理関数が存分に使えるという利点がある。

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

「The Healthy Programmer」を読んで自宅を快適なプログラミング環境にする

柄にもなく健康の話をします。

去年の今頃は京都から東京に引っ越してきたところでした。まだはてなで働いていましたが、勤務形態は自宅からのリモートが主になっていました。週に6日は家から出ずに家でコードを書いていました。昼から早朝まで書いて昼からまた早朝までコードを書くような、ある意味規則的な生活です*1

この間、生産性はかなり上がっていて、起きているときはもちろん、寝ている間も脳が活動を続け、睡眠中に考えたアイデアを唐突に起き上がってホワイトボードに書き込むみたいな状態でした。

しかし、1ヶ月くらいすると体調が悪くなってきます。なんか左脳の後ろ側が死んでるみたいな。

あと心臓が異常にバクバクする。座るのもきつくなってくるのでだいたいダメ人間ソファに沈んでHHKB叩いてるみたいな様子でした。

そして生産性も下がってくる。

リモート勤務を行うチームのマネジメントの難しさは最近よく語られるところですが、リモート勤務をする個人の話はそれほどは多くありません。特に健康についての難しさの記事とか見たことがありません。

新しく入った会社でも基本自宅でのリモート勤務なので快適な反面、健康問題は続きます。

The Healthy Programmerを手にする

そんなとき知人に推薦されて「The Healthy Programmer」という本を知りました。

Kindle版があったので早速買いました。3分の1ほど読んだあとにしばらく積ん読になっていましたが、最近改めて手にとって通読しました。

コードを書き続けるために健康になる

健康系の情報ってだいたい「運動しよう」とか「ダイエットしよう」とか「血圧を下げるには」とかいうものが多くて、むしろ栄養も血圧も筋力も足りてない系プログラマな僕には合いません。筋トレとか辛いし絶対したくない。家でじっとしてたい、みたいな。

The Healthy Programmerの違うところは、プログラマに特化していて、「コード書き続けたいよね? じゃあできるところからでいいから生活を改善してみない? ずっと座ってると腰痛くなったりして生産性落ちるじゃん?」みたいな気楽な感じです。

「健康になる」みたいな曖昧な目的ではなく、「コードを書き続けるために」という目的が一貫しているので好感が持てます。説教臭くないのも良い。

Exercise can increase your creativity, attention span, and ability to remember new concepts. Furthermore, reducing pain can help you focus and concentrate better.
運動はクリエイティビティを上げ、注意力を持続し、新しい概念を習得する能力を上げます。さらに、苦痛を減らすことは集中力を上げてより専念できることに繋がります。

表現もプログラマっぽく書かれているのも少し面白い。「健康をリファクタリングする前に、まずは自分の健康をユニットテストしましょう」とかナチュラルに出てきてちょっと笑えます *2

運動 ≠ つらいもの

でも、「そうは言ってもきつい運動とか毎日できる気がしないんですよね〜」と思いましたよね。

生まれてこのかた筋トレなんてしてないし、一番筋肉がある部分って心臓と横隔膜なんじゃね、っていう有り様なので、運動は嫌です。

そうやって身構えていたのですが、最初に出てくる運動が「散歩 (Walking)」です。

Walking is a powerful activity. It can stimulate creative thinking and it's the best way to bootstrap your health.
散歩はとても効力のある運動です。創造性を刺激し、あなたの健康をブートストラップする最良の方法です。

「1日8時間も座り続けている」というのがどれだけ健康リスクがあることなのかを説明し、「20分以上座り続けていてはいけない」と言っています。足を動かさないと足に流れた血が上半身まで戻って来づらくなるため、血の巡りが悪くなって脳に血液が回りづらい状態になるため、脳の働きも悪くなります。

歩くだけでなく、単に立つのも良いとされています。ずっと同じ姿勢をしているのが非常に良くないということだそうで。

立つ (Standing)

最近はIT企業でもスタンディングデスクを導入しているところもありますね。座り疲れたら立った状態でMacBookをカタカタやるやつです。

なので自宅にもカウンターテーブルを置きました。

AY ブルノハイテーブル AT-125CT(BR)

AY ブルノハイテーブル AT-125CT(BR)

こんな感じ。

f:id:nitro_idiot:20150211115614j:plain

ただ、このカウンターテーブルはスタンディングデスクとして使うには高さが少し足りなくて、スタンディングデスクするときは適宜本を敷いています。

f:id:nitro_idiot:20150211150231j:plain

立ち続けるのも良くない

とはいえ、ずっと立ってるのも良くないようです。膝に負荷がかかる。

Dr. Hedge recommends sitting for no longer than twenty minutes, but you shouldn't stand for longer than twenty minutes at a time, either.
ヘッジ博士は20分以上座り続けないことを推奨していますが、同時に20分以上立ち続けるべきでもありません。

立ったり座ったりを繰り返すのが良いようです。そのためにMacを移動するのも面倒なので、カウンターテーブルで立ったり座ったりする、というのをおすすめしています。

最近はスタンディングデスクやバランスボール (Exercise ball)が純粋に良いもののように語られることが多いですが、それも必ずしも良いというわけではない、たとえば足や腰を痛める可能性があったり、高血圧の人には悪影響、などの公平なアドバイスもあります。

ちなみにWobble Boardという、"スタンディングバランスボール"とでも言うべきようなものもあるようです。

絶対家にあってもやらないと思ったのでこちらは買っていません。会社にあると面白いかも。

サイクリング (Cycling)

The Healthy Programmerの論調として、「○○をしたら健康になれる」というのはありません。だから歩けば良いとか、立てば良い、というわけではなく、重要なのは同じ姿勢を20分以上続けないこと

  • Work from at least three different positions every day.
  • Don't stay in any one position for longer than twenty minutes.
  • Keep more than one kind of chair your office -- a regular office chair, an exercise ball, a drafting stool, or even a cycling desk.
  • 毎日最低でも異なる3ヶ所から仕事をする
  • 20分以上同じ場所に留まってはいけない
  • オフィスでは1種類以上のイスを使うこと -- 普通のオフィスチェア、バランスボール、可動式のイス、さらに言えばサイクリングデスク

リモート勤務する僕にとっては自宅がオフィスです。普通のイスとカウンターテーブルは用意しました。

f:id:nitro_idiot:20150211120245j:plain

あと一個か…。

というので、エアロバイクを買ってみました。

ALINCO(アルインコ) クロスバイク AFB4513

ALINCO(アルインコ) クロスバイク AFB4513

f:id:nitro_idiot:20150211121017j:plain

ALINCOという会社が有名のようで、その会社の折り畳み式のエアロバイクです。「ジムのものと比べて負荷が軽すぎる」とか「30分以上連続稼働できない」とか書かれていますが、僕の場合は筋トレをしたいわけではないので問題ありません。っていうかこれ3分くらい漕いだら普通に疲れるんですが…。

漕いでいるときの音も異常に静かで、加湿器とかエアコンの音にかき消されて聞こえないくらいです。コンセントに繋ぐ必要もないし、来客のときは移動したり折りたたんだりできる。

リビングに置くのが割と重要だと思っていて、寒い外に出なくても、短時間でも気楽に運動できるのは良さそうです。

まとめ

The Healthy Programmerを読んだし、少し広めの家に引越したついでにいろいろ家に投資してみるか、と思って導入してみた話でした。

最近IT業界でも健康について語られることもありますが、「なぜ良いのか」とか「デメリットはあるか」とかがあまり語られず、曖昧に運動したほうがよさそうという程度にしか語られません。

その点The Healthy Programmerは最近の研究に基いて良いところ・悪いところを公正に書いているので読んでいてすっきりします。

今回は自宅の改善に関連するところだけ取り上げましたが、この本自体は幅広い内容を扱っています。

興味があれば読んでみてください。Kindleで読めます。

※追記: 翻訳版が今年の夏頃にオライリーから出版予定のようです。日本語で読みたい方はそちらを待つと良さそう。

*1:この頃に生まれたのがLesqueIntegralCL21です。

*2:著者のJoe Kutnerさんは現役プログラマのようで、表現の選択のセンスも割と良い。

Clack Meetup #1 を開催します

f:id:nitro_idiot:20150120165947p:plain

3月5日 (木) に「Clack Meetup #1」というイベントをサムライト株式会社のオフィスにて開催します。

Clackは拙作のCommon LispにおけるWeb application environmentであり、4年前にリリースされてから先日ようやくv1.0がリリースされました。

Clack MeetupではそのClackと共に、その周辺のエコシステム――WebフレームワークやDBアクセスライブラリ含む――の、Common LispのWeb開発全般の話を扱う予定です。

サムライトでの導入事例など、実際に動いているプロダクトの話も少しする予定なので、興味がある方はぜひご参加ください。

高速なCommon LispのWebサーバ「Woo」を作りました

ここ一ヶ月ほど手掛けていたCommon LispのWebサーバ「Woo」が一応の完成に至りましたのでお知らせします。Clack-compatibleなAPIになっており、現状運用しているClackのWebアプリケーションでそのままお試しいただけます。

高速であることを最優先に設計しており、Hunchentootの4倍、Wookieの3.5倍高速に動きます。現状ではCommon Lispのサーバでは最速ではないでしょうか。*1

Benchmarks

いくつかのCommon Lispのサーバと、Node.js、Go、Pythonのサーバを比較してみました。縦軸はreq/secで、高いほうが多くのリクエストを捌けることを意味します。

f:id:nitro_idiot:20141219152449p:plain

Wooは、PythonのTornadoより約9.5倍、Node.jsの約1.9倍のリクエストを捌けます。一方、Goには少し負けています。

この結果を以ってNode.js遅すぎとか言うつもりは全くなくて、むしろNode.jsがRubyPythonと比べて2倍以上の差をつけているのは純粋に驚きました。Node.jsが速いと言われるのもわかります。

複数CPUコアを有効に使えるように、Workerプロセス数を指定したベンチマークも取りました。

f:id:nitro_idiot:20141219153408p:plain

こちらではRubyUnicornをnginxの裏に置いて試してみました。WooはUnicornの約2.4倍以上のパフォーマンスが出ています。Goよりはさらに差がつけられてしまっていますね。子プロセスへのディスパッチをまともにやらなければ。

ベンチマーク方法などの詳細はWooのリポジトリのBenchmarkをご覧ください。

Installation

インストールには以下のものが必要です。

その後、GitHubからWooをcloneしてbenchmark/woo.lispを実行するとサーバが立ち上がります。

$ mkdir -p ~/common-lisp && cd ~/common-lisp
$ git clone https://github.com/fukamachi/woo
$ sbcl --load woo/benchmark/woo.lisp

Why so fast?

WooがHunchentootやWookieに比べて圧倒的な差をつけているのはなぜ?と聞かれます。

最も大きいのは、non-blockingなサーバであり、さらにWookieと違って裏側でlibevを使っていることが大きいです。これで1.5倍くらいは違いますね。 *2

その他はアプリケーションレベルのボトルネックを丁寧に一つ一つ取り除いていきました。

おわりに

WooはGitHubにて公開されています。フィードバックをお待ちしています。

また、Wooは雇い主であるサムライト株式会社の全面的な協力を得て完成を迎えました。現在サムライトではCommon Lisperを募集しておりますので興味がある方は以下のWantedlyからご応募ください。

*1:高速なものとしてteepeedee2が有名ですが、CFFIのAPI変更に追随しておらず動かないようです。同僚が修正を加えた上でLinuxで試したところ、Node.jsより少し速い程度だった、と言っていたのでたぶんWooのほうが速いんじゃないかな

*2:ベンチマーク時のWookieはlibevent2を使っており、現状はlibuvに移行しています。どちらもlibevよりオーバーヘッドが大きく遅い。