Emacsは死んだ

[English, Korean]

-- 松山朋洋 (2010/2/22)

何よりもまず最初に、あまりにも感傷的なタイトルを付けたことについて謝罪しなければなりません。この記事を少しでも読めば、私がいかにEmacsを愛しており、永遠に不滅だと思っているか、理解していただけると思います。ただ、逆にそうであり過ぎるが故に、このようなタイトルを付けてしまったのだと自己分析しています。なんにせよ皆様の寛大さでもって見逃していただければと思います。

この文書は、未踏ユースの最初の発表会の時に行った私のプレゼンを、一部抜粋して文書化したものです。私のHDDと頭脳に永遠に眠らせておくこともできたのですが、もしかしたら社会にとって価値があるかもしれないと思いあたり文書化した次第です。皆様がつまらないと考えるなら、本当につまらないものでしょうし、面白いと考えるのなら、少しぐらいは価値のあるものなのかもしれません。どちらしても私の将来には大した影響力がないでしょう。能書きはこれぐらいにして本題に移ります。

Emacsの思想

最初に断っておきますが、ここで話す「Emacsの思想」というのは私個人が勝手に作りあげたものです。私の知る限り、ストールマンを含めて誰も「Emacsの思想」を語っているのを見たことがありません。特にストールマンなどは彼のもっと偉大な目標である「自由の思想」に向かって運動を続けているため、「Emacsの思想」などという小さい問題は眼中にないと言ったところでしょう。とにかく言いたいのは、後援が誰もいないため思想的価値が著しく低いということです。その点だけ気をつけてください。

まず、言うまでもないと思いますが、Emacsの最大の特徴はEmacs Lispにあります。Emacs LispはLisp方言の一つで、正直に言えば(Vimスクリプトほどではありませんが)、RubyやPythonなどの他の動的型付け言語などと比べてランタイムやライブラリの充実度でかなり劣ります。それでも、EmacsのCコアの最小化や、Lisp特有の拡張性により、Emacsユーザーは自分の好みに合わせて、かなり大規模にEmacsを変更することができます。革新的なインターフェースでEmacs界を驚かせたanything.elや、最近個人的にホットなundo-tree.el[1]は、Emacs Lispの土壌がなければ決して実現されなかったことでしょう。ところが先ほど申したとおり、Emacs Lispはランタイムとしては優れているとは言えません。現状の問題点を以下に挙げます。

  1. マルチスレッド対応の欠如
  2. 共有ライブラリ対応の欠如
  3. ファイルIOなどの低レイヤーAPIの欠如

これらの問題点は、Emacs Lispでより高度な機能を実装する障壁となっています。例えば、マルチスレッド対応が欠如しているため、ユーザーの編集作業をブロックせずに、バックグラウンドで重い処理を行うといったことが簡単に行えません。あるいは共有ライブラリ対応が欠如しているため、高度な機能を有する共有ライブラリをEmacs Lispから直接扱うことができません。あるいは低レイヤーAPIの欠如のため、より本格的で高速な処理をEmacs Lispのみで行うことができません。

これらの問題を回避するための一般的な方法として、外部プログラムを使う手法が昔から採用されてきました。例えばリモートマシンのファイルを直接編集する機能であるTrampは、sshやftpなどの複雑な外部プログラムをEmacs Lispから操作することにより、Emacs上での編集インターフェースを提供しています。あるいはバージョン管理機能であるVCは、複雑なsvnやgitなどの外部プログラムを利用して、あたかもEmacsでバージョン管理しているようにみせかけます。この他にも、標準搭載されている機能の多くが外部プログラムに依存する形で実装されています。この手法が優れているのは、Emacs Lispはその得意分野であるユーザーインターフェースに集中して、その他複雑な部分は外部プログラムにまかせようとする点です。Emacs Lispはランタイムとして劣っているので、このような作業分担は大変理にかなっています。そしてその作業分担の嬉しい副作用は、Emacsの優れた機能を外部プログラムとして定義できる点です。さらに嬉しいことは、Emacs Lispと外部プログラムのデータ通信はプロセス間通信として可視化されるため、再利用性が大幅に膨らむということです。

ここで一つ思考実験をしてみましょう。例として、EclipseとEmacsにRubyのためのコード補完機能を実装することを考えてみます。EclipseはJavaを基底としたプラグインアーキテクチャを採用しており、(その他多くのプロダクトでも言えることですが)データ構造を内包して効率よく処理することが良しとされています。Rubyのためのコード補完機能という素晴しい機能は、もしもEclipse上に実装するのであれば、それはEclipseに閉じたものになります。試しに「Eclipse Ruby」で検索してください。いくつかのプラグインを見つけることができますが、全てがEclipseに閉じていることが分かると思います。そしてそれらは得てしてEclipseと強結合されているため、Eclipse以外のプラットフォームから利用するのがかなり難しくなっています。仮にそれが可能であったとしてもメインラインからの度重なるマージで疲れはてることになるでしょう。

さて、Emacsについてはどうでしょうか。実際的な理由、つまりEmacs Lispはランタイムの問題により、Eclipseの時のようにEmacs上に直接、Rubyのためのコード補完機能を実現するのは非常に難しく思えます。そこで伝家の宝刀である外部プログラム化を考えます。外部プログラム化の方法には特に制限がありません。自分の好きなように実装して、コマンドラインインターフェースあるいはネットワーク通信インターフェースを作ればいいのです(コマンドラインインターフェースを推奨)。後はEmacs Lispでその外部プログラムとプロセス間通信なりネットワーク通信で会話すれば目的の機能を実現できるはずです。

もうお気付きだとは思いますが、Eclipse版とEmacs版での大きな違いは、外部プログラム化されるかどうかです。Eclipse版では利用形態が限定されるのに対して、Emacs版では利用形態がEmacsのみに限定されることはありません。少しコードを書けばVimからでもTextMateからでも利用できるようになるでしょう。このような社会的価値の増大のさせ方はGPLに似ていると感じることがあります。つまり個々人の自由を少し制限することにより、全体の自由を最大化させるということです。

以上を要約すると、Emacs Lispにはランタイムとしての欠陥があるため、結果的に外部プログラムによって潜在的な社会的価値を最大化させるインセンティブが働きやすくなると考えられるということです。ただしこれは歴史的な解釈に過ぎないのかもしれません。現在の(私の)視点から言えば、逆に、社会的価値を最大化させるために、Emacs Lispのランタイムにはあえて欠陥が設けられている、と言ったほうが正しいと考えています。正確な話かは定かではありませんが、かのストールマンもEmacs Lispから共有ライブラリを利用できるようにする変更に対して断固反対していたようです。その裏側には上記したような社会的価値の最大化の問題があったのかもしれません。つまるところ、私は、このEmacs Lispの意図的(かどうかはわかりませんが)な制限は、ソフトウェアの社会的価値を増大させるという「Emacsの思想」を根拠としており、そしてそれは未来永劫守られるべきものだと考えています。

新しい時代の到来とその問題

コンピュータの性能の向上は著しいものがあります。性能の向上により様々な分野で新しいニーズや研究が生まれていますが、Emacs界でも他に漏れずニューウェーブが到来しています。その中でも特に言及したいのが、js2-modeとSemanticです。まずjs2-modeから話します。

js2-modeSteve Yeggeという少し変わった開発者によって作られた新しいJavaScript用メジャーモードで、その特徴としてEmacs Lispで実装されたJavaScriptインタプリタを持っていることが挙げられます。彼はEmacs自身がJavaScriptインタプリタを持つことにより、より高度でインタラクティブなエラーチェックやコード補完、さらにはリファクタリングを行えるようになると考えています。それらの機能を正しく実現できるかどうかは知りませんが、彼の推測自体は非常に的を得ています。従来のシンタックスエラーなどのエラーチェックは、標準搭載のFlymakeという拡張で実現していました。Flymakeは、バッファが保存されたタイミングやオートセーブのタイミングで、適切なエラーチェックプログラムを起動し、その出力を解析して、エラーがあればバッファ上の問題行をハイライトする、という単純な作りになっています。(Emacsでは一般的ですが)このように外部プログラムに依存している場合、外部プログラムとのデータの不一致のため、上記したような機能をうまく実装できないことが多々あります。その点をEmacs Lispで記述されたJavaScriptインタプリタでカバーしようと彼は考えているようですが、この考えが不幸なのは、Eclipseと同じ轍を踏んでいるところにあります。仮にjs2-modeが最高に素晴しいソフトウェアになって、Emacsユーザーに大変感謝されたとしても、それがVimからでもTextMateからでもその他多くのソフトウェアからでも利用できないのであれば、私はそれに大した社会的価値があるとは考えません。もし私が述べた「Emacsの思想」が正しいと思うのなら、このような排他的な戦略を取ることに全く意味はありません。データの不一致など、乗り越えるべき壁は多数ありますが、まず第一に、Emacsを使っている以上、我々は社会的価値の最大化を重視するべきだと私は思います。

次にSemanticの問題を話します。これはjs2-mode以上に重大な問題だと私は考えています。というのもSemanticが、全てEmacs Lispで実装されたパーサー群を提供しようとしているからです。さらに問題なのはEmacsのメインラインにマージされて次のリリースで標準搭載になってしまうことです。まず、Semanticそのものについて説明します。SemanticとはEmacs Lispで記述できるパーサージェネレータおよびパーサー群であり、Semanticの野心的な目標には、例えばC++のコード補完などの巨大なものから、タグジャンプのような小さいものまであります。開発自体はかなり昔から少しづつ進行しており、Emacsとコード補完の検索でヒットするほとんどの文書はSemanticに関連があります。長年の蓄積もあって、そこそこ正常に動作しているようで、皆さんも(知らない間に)Semanticの機能を利用していることでしょう。Semanticに関して私が唯一フォローできるとしたら、Emacs Lispのテキスト処理能力に目を付けたという一点だけです。しかし、この謙虚なフォローすらも上記したランタイムの欠陥が見事にとどめを刺すので、結局のところ私には何のフォローもできないのです。

それではSemanticの問題に移ります。上記した通りSemantic(およびその親パッケージであるCEDET)には以下の二つの致命的な問題があります。

  1. Emacs Lispで記述されている
  2. Emacs 23.2で標準搭載される予定

(1)の問題はjs2-modeでの問題と共通しており、要はSemanticで実現された価値がEmacsに閉じてしまい、社会的価値の増大が図れないのが問題になります。これは「Emacsの思想」に相反するものであり、Eclipseに至る危険な一歩を踏み出した証になります。そしてその危険性を何倍にも倍増させるのが(2)の問題で、これは要するにEmacs開発チームが「Emacsの思想」を完全に無視したことを意味しています[2]。これは他のソフトウェアへの排他行為であり、社会的にモラルの欠いた行為であると私は考えます。これが問題視されずにさらに進めば、Emacsのプラットフォームがさらに魅力的になり、その中に閉じたソフトウェアを作るインセンティブがさらに増大する恐れがあります。Emacsのプラットフォームが優れているのは、OSと協調するからであり、それ自体が優れているからではありません

小さいものを組合せて大きいものを作り上げるという美しいUnixの伝統がEmacsには脈々と受け継がれています。そしてその美しさこそが、私がEmacsを使う最大の理由なのです。しかし、それはもはや過去のものになりつつあるのかもしれません。美しさや思想が排除され、便益のみが残った世界に何の意味があるのでしょう。Emacsがそうなってしまうのは悲しくて仕方がありません。

我々はどうすべきか

これは難しい問題です。そもそも悲観視しすぎかもしれません。とにかく我々にできることと言えば、「Emacsの思想」にできるだけ従うことだと考えています。ソフトウェアの利用を止めるなどの実力行使は避けるべきです。可能な限りの寛容さをもって、優れた手段を提案していくというのがベストでしょう。


この文書はCreative Commons Attribution-Noncommercial-No Derivative Works 3.0のもとでライセンスされています。


  1. undoヒストリをツリー状にみたてて何如なる変更バージョンにも戻ることができる革新的なundo機能

  2. もともとそんなのはないのかもしれませんが