手動エスケープは有害である

多くのプログラミング言語は文脈自由文法を使って文法を定義している。その結果、ソースコードは綺麗な階層構造を持つことになる。

そして意味が抽象構文木に対して定義される・・・・本当にそれだけだろうか?

def add(x,y):
  """ 2数を足す """
  return x+y

と書いてあるとき、「2数を足す」の部分が意味をなすのはそれが日本語だからだ。このとき"""..."""の記号は単にある文字列を決めているだけではなく、Python-日本語という違う体系の境界になっている。そして、内側で"を使おうと思ったら、エスケープ文字を使って\"と書いたりするわけだ。

ここまではいい。うまい規則で文字を組み合わせると、文字の種類が有限しかなくてもいくらでも深く階層構造を表せるテクニックがあるということだ。問題は、人間がそれをやってるという現状にある。

言語とファイルの乱立

さっきの例は文字列が短いから特に問題は感じなかったかもしれない。では、次の例はどうだろうか。

var content = '<div class="foo">' +
  '<h1>Lorem Ipsum</h1>' +
  '<div>'+x+':'+y+' : <a href="http://www.example.com/get?q='+x+'">xxx</a>' +
  '</div>';

かなり見にくくて、一見正しいかどうかわからない。実際この例ではdivが閉じていない。普通にHTMLを書いていて、シンタックス・タグ対応ハイライトがあればすぐに分かるにもかかわらず。

で、ここで例えばjQueryを使って、

var content = $('<div/>').addClass('foo');
cotent.append($('<h1/>').text('Lorem Ipsum');
...

と書けばいいという問題ではない

それぞれの言語は、それぞれが扱うものが書きやすいように作られている(はず)で、なんでも1つの言語で書けばいいというものではない。*1

こういう問題が今どう対処されているかというと:

  1. ファイルを分割しまくる
  2. 言語を作りまくる
ファイルを分割しまくる

1はわりと単純で、違う言語で書きたい部分を別のファイルに分けてロードしたりする。しかしこれには問題がいくつもあって、

  • 意味が近いものの場所が離れてしまう
    • → ファイル名をつけて管理しないといけない
  • 余計なIOが必要になる
  • ちょっとだけ混ぜるのが難しい (さっきのxとかyみたいな部分)

特に最後の問題はこの方法だけでは解決できない。

言語を作りまくる

汎用的ながらすごく筋の悪い解決策として、2つ以上の言語の特性をほどほどに併せ持った言語を作るという方法がある。

たとえばweb系でテンプレート言語と呼ばれているものは、django,haml,jinja,mustache...と(言語の数)*(配合の度合い)で無数に存在する。

もうひとつ乱立が目立つのが軽量マークアップ言語と呼ばれているもので、wiki記法に始まりmarkdown,reST,textileと盛り込む機能によって無数に存在し、これらの汎用の構造化テキストとは別に各プログラミング言語のドキュメント記述用言語というのも大量にある。

言語に盛り込む機能と記述の簡潔さにはトレードオフがあり、簡潔な記述は皆の好物なので、用途ごとの特徴セットに対して言語が出来、指数関数的とまではいかなくとも何乗かで増加することになってしまう。そして、Internet of Thingsなどと言われる中、プログラムしたい対象の多様性は増える一方だ。

このままどんどん増加する言語たちに押し潰されるしか無いのだろうか?

エディタの役割

ここで基本に立ち返ってみる。これらの言語をどうやって見て・どうやって書いているか?―エディタだ。*2

ここでもう一度普通のハイライトを見てみよう。

var hoge = "<div>ほげ</div>";

ここでエディタが持っている知識を考えてみる。文字列リテラルのハイライトにはエスケープの仕方のかなりの部分が必要だ。つまりちょっとの手間で境界の中と外を明確に区別できる。そして、このようなエディタはjavascriptもHTMLも知っている

・・・なぜ両方の文法を同時に適用できないのか?

深いシンタックスハイライト+自動エスケープ


つまりこういうことだ。javascriptとHTMLの両方で同時にハイライトされている。そしてエスケープは暗黙に処理されて、より本来の境界の意味に近い枠で表されている。

動作デモ

http://xanxys.github.com/deep_syntax/
とりあえずplaintext/HTML/javascriptのごく一部をサポートしている。"..."と書くと領域ができるので、そこをクリックすると編集対象が切り替わる。

ちゃんとカーソルを出せてないというところはいいとして(よくない)、表示の仕方は折り畳みできるようにするとか、半透明に重ねるようにするとかも考えられる。とはいえ、デフォルトでは展開している方が読みやすいコードを書くインセンティブが生じていいと思う。

モノリシック文法・マイクロ文法

こうして細かい粒度で言語を切り変えられるのを前提に考えると、1つの言語はどこまでシンプルになれるだろうか?たとえば文字列もコメントも、ちゃんとエスケープできるものが1種類あればそれでいい。文の並びはエスケープ可能な配列の記法があれば言語のコアに含める必要はないのではないか・・・?

今までの文法を多くの機能を摺りあわせたモノリシック文法と呼ぶなら、このように単機能に特化した、部品としての文法はマイクロ文法と呼べるだろう。

今回は異なる系の組み合わせの記述だけを見た。

これを実行時に拡張するとどうなるだろうか。・・・それについては見えてないけど、まだまだ面白いことはありそうだ。

*1:なんでも同じぐらい書きにくいのがLisp

*2:IDEでもいいが、ここの議論において本質的な違いはない