最近開催されたEmerging Languages Conference (OSCONの一部)で、DocumentCloudの主要開発者であり、underscore.jsの作者であるJeremy Ashkenas氏が、JavaScriptにクロスコンパイルされる言語であるCoffeeScriptに関する講演をおこなった。
ちょうど今日、CoffeeScriptのバージョン0.9.0がリリースされた。互換性が崩れる主要な変更は、代入演算子がコロン : から、よりJavaScriptに近いイコール = に変更されたことだ。この変更は十分な議論を経て決定されたのだが、主にYAMLスタイルのオブジェクトリテラルと名前付きのパラメータを可能にするためにおこなわれた。 Half assignments(a : or 'default')も言語から取り除かれた。また、いくつかの改良点が、(オプションの)クラス継承システムに取り入れらられている。
このような言語は他にもあるが、私たちがここでとりあげるのは、CoffeeScriptが目的と特徴で他と異なるからだ。Jeremy氏は、私たちの質問に答える中で、洞察を与えてくれた。彼の回答がこの記事に反映されている。
Jeremy氏はJacaScriptを集中的に使って仕事をしてきて、その欠点を直に経験してきた。彼は、CoffeeScriptの背後にある意図を次のようにまとめた。
CoffeeScriptは、JavaScriptの根底にある美しいオブジェクトモデルのための最小限の構文を示す単純な思考実験なのです。これを実現するために3つの主要な要素がある。軽量な構文をもつこと、ばらばらになったJavaScriptの構成要素の意味をきれいにまとめあげること、一般的なJavaScriptのパターンを簡潔に表現できるおまけの言語機能を提供することの3つである。 CoffeeScriptの対象となる人々は、ブラウザ上で動作する可読性のあるコードを書きたいと望んでいる人や、JavaScriptの優れた部分は利用したいのだけれど、暗い小道は避けたいと考えているような人だ。
近年の強力なJSエンジン(V8やNitroなど)の登場により、JavaScriptは高速で強力な動的言語となった。JavaScriptがWebアプリケーションや、最近ではイベント駆動のノン・ブロッキングサーバーの実行環境(Node.jsなど)として広く利用されるようになったことで、近い将来、JavaScriptは欠かすことのできない言語となるであろう。パフォーマンスや、言語がよく知られていることに加えて、新たな要素として、JavaScriptのコードやライブラリをクライアントとサーバで再利用するということがあげられる。特にドメインモデルでは、データの検証とアプリケーションロジックを共有することができる。
Jeremy氏は次のように明確に語った。 「JavaScript Webアプリケーションのためのエンド・トー・エンドの満足のいくシステムを最初に作ったら、次の5年のWeb開発の時代の勝者となるでしょう。」
これらの理由によって、Jeremy氏は、JavaScriptを標的とするプラットフォームとしている。JavaScriptをベースとしているとはいえ、CoffeeScriptはPythonの影響を強く受けており、Haskellなどの関数型言語や、そしてもちろんEcmaScript 5およびEcmaScript Harmony Wikiからの多くの示唆の影響を受けている。 CoffeeScriptが対象としている主要な3つのエリアは次のようなものだ。
構文の整理
- Pythonスタイルの重要な意味をもつスペース
- 暗黙の丸括弧
- セミコロンの不使用
- Stringの継続
- 簡潔な関数リテラル
- YAMLスタイルのオブジェクトリテラル
セマンティックの拡張
- すべてのものが式(expression)である(値を返す)
- ローカルの構文スコープの変数が、グローバルスコープを汚染しない。
- 単純な代入と変数の宣言、分割代入
- 一連のif-then-elseにコンパイルされるswitch構文
- 連結比較式(chain comparisons)
- 名前付きパラメータ
Goodies
- 可変長引数リスト(splats)
- 文芸的プログラミング (ドキュメントのなかにコードを書く)
- pythonのレンジ、配列、オブジェクトの内包表記(comprehensions)
- 実在(existential)(エルビス)演算子
=>ハッシュロケット演算子を利用した明示的な現在のオブジェクトの関数への強いバインディング- 高速できちんと動作するクラスを基にした継承のサポート、これはgoogle.inheritのアプローチを基にしている
- 静的な継承のサポートとスーパークラスのメソッドへの自動的な委譲
- ヒアドキュメント、複数行の文字列、リテラルとしての正規表現、文字列の差し込み/置換
- CakeというRakeに似たビルドシステム
- <script type="text/coffeescript">タグ、インラインで利用するための縮小したcoffescriptコンパイラ
ドキュメンテーションから引用した、いくつかの例をつかって、これらの機能を見ていこう。
# 代入:
number = 42
opposite = true
# 条件:
number = -42 if opposite
# 関数:
square = (x) -> x * x
# 配列:
list = [1, 2, 3, 4, 5]
# オブジェクト:
math =
root: Math.sqrt
square: square
cube: (x) -> x * square x
# 名前付きのパラメータ
fun key : value
(call({key: value}); にコンパイルされる )
# Splats:
race = (winner, runners...) ->
print winner, runners
# 存在演算子:
alert "I knew it!" if elvis?
# Accessor existence operator (null safe)
lottery.drawWinner()?.address?.zipcode
# 配列の内包表記:
cubes = math.cube num for num in list
# オブジェクトの内包表記:
yearsOld = max: 10, ida: 9, tim: 11
ages = for child, age of yearsOld
child + " is " + age
# 分割代入
[city, temp, forecast] = weatherReport "Berkeley, CA"
[open, contents..., close] = " ".split("")
# 関数とthisの強いバインディング
Account = (customer, cart) ->
@customer = customer
@cart = cart
$('.shopping_cart').bind 'click', (event) =>
@customer.purchase @cart
# 正規表現と文字列置換
sep = "[.\\/\\- ]"
dates = /\d+#sep\d+#sep\d+/g
CoffeeScriptは、githubレポジトリをクローンし、内包されるビルドシステムCake(Rakeに似たもの)をビルドのために利用することでインストールできる(sudo bin/cake install)。npm(Node Package Manager)も同様に簡単だ(sudo npm install coffee-script)。これでcoffeeコンパイラが利用可能となり、CoffeeScriptをJavaScriptにコンパイルしたり、対話式に実行したりできるようになる。
coffeeは自分自身をコンパイル可能な(self hosted)CoffeeScriptコンパイラだ。
自分自身をコンパイル可能な(self hosted)言語のトリックは土台となる部分から始めなければならない。オリジナルのCoffeeScriptコンパイラはRubyで書かれていた。バージョン0.5.0で、Rubyバージョンのまさに1対1のポーティングを行い、それをコンパイルし、新しいコンパイラをそれ自身のコードで動かした。そしてすべてのテストを自身でコンパイルを行ったバージョンで実施した。確かに心臓がとまるかと思うような瞬間だった。[...]自分自身をコンパイルすることにより、より正直になれるんだ。普通出会わないようなバグやパフォーマンス、生成されるコードの綺麗さを意識しつづるようになる。
CoffeeScriptは、ソースコードのレベルでJavaScriptにコンパイルするので、(負の配列添え字のような)要望を受けている言語機能でも実現することが不可能なものがある。少なくともJSの実行環境にアクセスすることなしには不可能だ。
他のクロスコンパイルの側面としては、実行時のトレースや生成されたJavaScriptのデバッグがあげられる。行番号が一致しないので、JavaScriptのコードと、もととなったCoffeeScriptを対応づけるのは困難だ。こういう理由があり、Jeremy氏は可読性の良いJavaScriptのコードを生成するよう特別注意をはらっており、事前にコンパイルを行い、JSコードを直接デプロイおよびデバッグすることを勧めているのだ。したがって、CoffeeScriptはコード生成言語として機能するのだ。
CoffeeScriptを作成する労力に関して、Jeremy氏は、これはロケットサイエンスではないのだと記している。
CoffeeScriptは、たった2,090行のコードからなっており、すべてに注釈がついている文芸的プログラミングスタイルだ。 もし、あなたのコードの書き方に沿う言語を作ってみたいのであれば、あなたの好きな実行環境を借りて、この合宿で紹介された言語のいくつかのソースコードで遊んでみることをおすすめする。たくさんの小さな言語の花をさかせよう。
CoffeeScriptの周りには、既に豊かなエコシステムが形成されている。さまざまなコミッタがいろいろなエディタ向けのシンタックスハイライトや、node.jsや、Rhino、Rack、Python、Rails3、Jammitといったものとの連携プロジェクトを提供している。
Jeremy氏のCoffeeScriptに関する講演は、TheChangeLog podcast episode 0.2.9やJSConf2010プレゼンテーションで聞くことができる。