BT

最新技術を追い求めるデベロッパのための情報コミュニティ

寄稿

Topics

地域を選ぶ

InfoQ ホームページ ニュース Javascript経由でClojureをブラウザで利用できるようにするClojureScript

Javascript経由でClojureをブラウザで利用できるようにするClojureScript

原文(投稿日:2011/07/26)へのリンク

ClojureScriptを使えばClojureを使ってコードを書き、それをコンパイルしてJavascriptにできる。ClojureScriptを発表したのはClojureの作者であるRich Hickey氏(ClojureScript発表のスライドビデオ)だ。

ClojureScriptはClojureの一部だ。現在実装されていない機能は単純でまだ実装が終わっていないものか、JavascriptのVM上では 動作しない機能、例えば、スレッドのサポートやJavaとの統合のような機能だ。ClojureとClojureScriptの違いはClojureScript Wikiにまとめられている。

なぜClojureScriptなのか

ClojureScriptの論理的根拠(ドキュメントによると): "Javascriptの動作範囲"。JavascriptのVMは高速になり様々な場所で利用できるようになっている。ClojureScriptを使えばClojureをGUIクライアントプログラミングでも利用できる。現在、HTMLの強力な部品とJavascriptのVMが使えるモバイルプラットフォームでも利用できるのだ。Clojureを実行するにはクライアントにJava VMが必要だが、多くのデスクトップOSではJava VMが利用できるものの、ブラウザの方がより普遍的でありあらゆるクライアントOSに搭載されている。モバイルプラットフォームではこの状況ははっきりとしている。現在、主要なモバイルプラットフォームの中でClojureがそのまま実行できるようなJava VMを搭載しているものはない。AndroidはJava VMを搭載していない。AndroidではすべてのバイトコードはDalvik VMのバイトコードに変換される。ClojureをAndroidで動作させるための開発は今も続いている

その他、コマンドラインユーティリティとしての使い方もある。Javaはコマンドラインツールにはほとんど使われていない。JVMの起動が遅い(Nailgunのようなソリューションは状況を改善してくれる)からだ。Rich Hickey氏のデモによれば、コンパイルしてJavascriptにしたコマンドラインをNode.jsで実行すると起動時間が劇的に下がる。

サーバでJavascriptを実行することについて頻繁に言われるのはサーバとクライアント同じコード再利用できるということだ。例えば、入力検証のようなロジックについてはよく言われる。 ClojureScriptを使えば同じことができる。ClojureScriptで書かれたアルゴリズムをコンパイルしてJavascriptにすることでブラウザで実行できる。そしてそのままサーバサードのClojure上でも実行できる。Javaにバイトコードに変換されて実行されるのだ。サーバからJavaを完全に除外してClojureScriptで書いたアプリケーションをNode.jsのようなJavascriptのスタック上で実行することもできる。

ClojureScriptの仕組み

ClojureScriptコンパイラにはJavascriptのコードを含まない。完全にClojureで書かれている。つまり、このコンパイラは実行するのにJava VMが必要だ。結果としてClojureScriptにはevalや実行時にコードをロードするような仕組みはない。ClojureScriptはコードを書いてそれをJavascriptにコンパイルするために使う。ブラウザ内REPLとしては動作しない。

しかし、ClojureScript REPL存在する。ClojureScriptリポジトリから利用できる。これはClojureで実装されていて、Javaで書かれたJavascriptランタイムであるRhinoによって実行される。ClojureScriptのスニペットを実行するには、そのコードをClojureScriptコンパイラに送り、その結果得られるJavascriptのコードをRhinoで実行するのだ。これをClojureにアクセスすることなしにブラウザ内で実行するのはもちろん不可能だ。誰かがClojureコンパイラツールチェーンをJavascript向けに作るまでは。

ClojureScriptではClojureマクロが使える。ClojureScriptのコードがマクロを呼び出すと、ClojureScriptのコンパイラ、つまりClojureがマクロの展開を実行する。

ClojureScriptコンパイラは現在、Clojure上だけで動作するが、ClojureScriptにはClojureリーダーが組み込まれている。 注意すべきは、このリーダーは基本的にはClojureのパーサであるということだ。これは、Clojureのプログラムの表現をClojureのデータ構造に変換する。このデータ構造にすることで評価が行える。このリーダーはClojure(Script)表記のデータを解析してClojureScriptのコードでデータとして扱えるようにする。ClojureScriptのリーダーは解析するだけだが、実行時にはClojureScriptのコンパイラは利用できないので、評価はしない
ClojureScriptにリーダーがあるのは、JavascriptがJSONのデータを評価することなしに読み取れるのと同じように、Clojureのデータを読めるようにするためだ。Clojureを使ってClojureのデータを生成し、ClojureScriptに送ることができる。その逆も可能だ。

そして、ClojureScriptのコンパイラツールチェーンにはGoogle Closureツールキットも含まれている。そう、Clojureの"j"が"s"になっている。不幸にも名前がぶつかってしまったが、GoogleのClosureのJavascriptツール、とりわけClosureコンパイラと高度コンパイルが使われている。
Closureを使う目的はいくつかある。ひとつはライブラリと依存関係の管理、つまり、必要なライブラリとシンボルのエクスポートの管理だ。ClojureScriptの名前空間の定義はGoogle Closureのproviderequireの呼び出しに対応する。また、Google ClosureのライブラリでリッチなGUI部品やその他の機能を簡単に使えるようになっている。
ClojureScriptははClojureにそっくりだが、標準ライブラリはClojureのライブラリの一部だ。現在clojure.string、 clojure.set、clojure.walk、clojure.zipなどが使える。今後、増えていくそうだ。ClojureのライブラリのClojureScriptへの移植の難しさはコードの性質による。言語の基本要素を使った純粋なアルゴリズムしか含まないコードの移植は簡単だ。しかし、I/Oやスレッドのライブラリや特定のJavaクラスに依存するコードは移植するのが難しい。特定のプラットフォームに依存するコードを除去しなければならないからだ。

さらに興味深いことに、Google Closureはコンパイラバックエンド最適化する。ClojureScriptの出力はClosureの高度コンパイル機能によって最適化される。Closureは出力結果のJavascriptのソースを受け取ると、関数呼び出しのインライン化や不要なデータやコードの除去などを行う。この方法の利点はClojureScript側でこのような最適化を行わなくてもいいことだ。Google Closureのコンパイラに任せてしまえばいい。
また将来的には、他の処理もGoogle Closureに移譲される。例えば、デバッガ用のソースの対応付けの提供、つまり生成されたJavascriptのコードと対応するClojureScriptのコードを対応付けるデータ構造の提供だ。Google ClosureはSourceMapをサポートしている。MozillaやWebKitプロジェクトもSourceMapをサポートしてデバッガやJavascriptエンジンの拡張を試みている。

ClojureScriptのさらなる詳しい情報はこれから増えるだろう。情報源のひとつはMichael Fogus氏のブログだ。氏はこのブログでこのコンパイラについて初めて一連の記事を書き始めている。氏はClojureScriptの実装にも関わっている。コンパイラの内部動作に興味がある開発者はClojureScriptの開発ノートを見るといいだろう。ここにはJavascriptの概念とそれに対応するClojureScriptの概念が一覧されているなどさまざまな情報がある。

ClojureのコミュニティはClojureScriptを使った実験を始めている。Brian McKenna氏はマクロを使ってコールバックの課題の解決に取り組んでいる。非同期I/Oでは処理の結果を得るためにコールバックの仕組みが必要だ。しかし、これを記述しようとすると、一回限りの呼び出しは上手く書けるものの、一連のアルゴリズムの中で書こうとすると冗長になってしまう。JSの世界ではこの問題に対して様々な試みがされてきた。StratifiedJSのような新しい言語での解決やJavascriptにDSLのようなライブラリ埋め込む方法もある。
氏は埋め込みDSLの方式での解決方法を模索している。ClojureScriptは、LISPのマクロのように、このやり方に適している。氏のサンプル実装では、一連の式をコンパイルしてネストしたコールバックにして、処理の中のひとつの式を実行し、setTimeoutを使って他の式の評価をスケジュールする。このやり方はモナドをサポートする言語でのプログラミング可能なセミコロンアプローチ(Haskellのdo表記)やF#のCompuational Expressions(例えば Async Workflows)を思い起こさせる。ループのような構造化プログラミングの概念をサポートするのが次の段階だろう。つまり、マクロを使ってこれらの結果を継続渡しのスタイルに変換するのだ。

Justin Grant氏のブログにはGoogle ClosureのCanvasのサポートを利用した描画の仕方とアルゴリズムの実装方法が書かれている

ClojureScriptはGitHubからダウンロードできる。clojure.comでのClojureScriptの発表GitHubのClojureScript Wikiを見ればClojureScriptの理論的根拠クイックスタートガイドなどさらに詳細な情報が得られる。またClojureメーリングリストではコミュティが開発ワークフローやツールについて議論しているので良い情報源になるだろう。

この記事に星をつける

おすすめ度
スタイル

BT