BT

core.async:ClojureとClojureScriptを使った非同期プログラミング

| 作者: Zef Hemel フォローする 0 人のフォロワー , 翻訳者 徳武 聡 フォローする 1 人のフォロワー 投稿日 2013年7月30日. 推定読書時間: 4 分 |

原文(投稿日:2013/07/24)へのリンク

Clojure/ClojureScriptライブラリのcore.asyncが発表されてから1ヶ月経過していないが、フロントエンドのコードで"コールバック地獄"を避けるためにこのライブラリを効率的に使う方法を説明したブログ記事が多数書かれており、単純なコードで印象深いインブラウザのデモを実現する例も生まれている。

core.asyncClojureで書かれたライブラリでClojureとClojureScriptで使うことができる。ClojureはJVMでのLispの実装だ。ClojureScriptはClojureの大きなサブセットの実装であり、JavaScriptにコンパイルできる。core.asyncはLispのマクロの威力を示す。ほとんどの他の言語ではcore.asyncが実現することを実現するには言語自体を変更しなければならないが、Lispの場合はマクロを使ってライブラリとして実装できる。

名前の通り、core.asyncは非同期プログラミングをシンプルにする。Goから多くのアイディアを拝借しているが、特にgoroutines (core.asyncのgo blocksにちなんで名付けられた)とチャンネルだ。チャンネルはひとつ以上のパブリッシャと1つ以上のコンシューマで構成されたキューだ。仕組みはシンプルで、キューにデータを置くと、コンシューマがキューからデータを取得する。Clojure/ClojureScriptのデータは不変なので、チャンネルは安全にスレッド間の通信を実現できる。しかし、スレッド間通信が安全に実現できるのは、ClojureScriptにとっては特に面白い機能ではない。JavaScriptはシングルスレッドで動作するからだ。

core.asyncはチャンネルからの読み込みとチャンネルへの書き込みにふたつの方法を提供する。ブロッキング方式とノンブロッキング方式だ。ブロッキング方式では書き込みはチャンネルが書き込める領域(バッファサイズは構成可能だ)を確保できるまでスレッドをブロックする。また読み込みではキュー上の値が読み込めるようになるまでスレッドをブロックする。興味深いのは、チャンネルに対する非同期読み込みと書き込みだ。これらは"go blocks"の中でのみ実行できる。go blocksは同期スタイルで書かれているが、内部では非同期に実行されるステートマシンに変換される。

次のコードはcore.asyncベースのコードだ。

(let [ch (chan)]
  (go (while true
        (let [v (<! ch)]
          (println "Read: " v))))
  (go (>! ch "hi")
      (<! (timeout 5000))
      (>! ch "there")))

この例では、letが新しいローカル変数chを導入する。この変数は新しいチャンネルだ。このletのスコープにはふたつのgoブロックが定義されており、最初のブロックはチャンネルであるchから値を変数vに読み込む(<!)無限ループで、読み込んだ値を標準出力に出力する。もうひとつのgoブロックはふたつの値をチャンネルであるchに書き込む(>!)。最初に"hi"を書き込み。5秒待ってから"there"を書き込む。5秒待つのは、timeoutというチャンネルからの読み込みによって実装している。このチャンネルは設定されたタイムアウト時間を過ぎるとクローズする(nilを返す)。このコードをClojure REPLで実行すると、すぐに結果が帰ってくる。"Read: hi"と表示され、5秒後に"Read: there"と表示される。

JavaScriptプログラマなら、このwhileループを見てパニックになってしまうだろう。このような方法でブロッキングのループを実行したら、ブラウザは5秒でフリーズしてしまう。core.asyncの"マジック"は内部で各goブロックの内部をステートマシンに変換し、同期のチャンネル読み込みと書き込みを非同期のコールに変えていることだ。

次に挙げるリソースはcore.asyncについて詳しく学び、フロントエンドの開発に活用するのに役に立つ。

この記事に星をつける

おすすめ度
スタイル

こんにちは

コメントするには InfoQアカウントの登録 または が必要です。InfoQ に登録するとさまざまなことができます。

アカウント登録をしてInfoQをお楽しみください。

あなたの意見をお聞かせください。

HTML: a,b,br,blockquote,i,li,pre,u,ul,p

このスレッドのメッセージについてEmailでリプライする
コミュニティコメント

HTML: a,b,br,blockquote,i,li,pre,u,ul,p

このスレッドのメッセージについてEmailでリプライする

HTML: a,b,br,blockquote,i,li,pre,u,ul,p

このスレッドのメッセージについてEmailでリプライする

ディスカッション

InfoQにログインし新機能を利用する


パスワードを忘れた方はこちらへ

Follow

お気に入りのトピックや著者をフォローする

業界やサイト内で一番重要な見出しを閲覧する

Like

より多いシグナル、より少ないノイズ

お気に入りのトピックと著者を選択して自分のフィードを作る

Notifications

最新情報をすぐ手に入れるようにしよう

通知設定をして、お気に入りコンテンツを見逃さないようにしよう!

BT