JavaOne Tokyo 2012 の JVM言語BoF でスピーカーしてきたよ

4/4-5 に行われた JavaOne Tokyo 2012 の JVM言語BoFに、スピーカーとして参加してきました。

BoFの概要は以下のような感じです。

JavaVM上で動作するさまざまなプログラミング言語 (Groovy、JRubyScalaなど) のコミュニティや興味を持つ個人が集まって、各言語のチュートリアルや最新情報、使用実績などの情報交換を行います。プレゼンテーション、各言語を使ったコーディング大会、ライトニング・トークなどの形式で、ユーザ間の交流を促すBoFとして開催し、言語を超えて活用が進むJavaVMの日本ユーザの裾野を広げます。飛び入り参加大歓迎、楽しい時間にしたいと思います。

https://oj-events.jp/public/session/view/173

僕は ScalaJP からコーディング大会の Scala 担当として発表させて頂きました。

あのじゅんいち☆かとうさんをしてエロガントと言わしめたScalaのコードがこちらになりますw

セッション中の時間では説明し切れなかった部分も多かったので、改めて補足してみようかなと思います。

Twitter連携

一つ目のお題はTwitter連携でした。レギュレーションの詳細はこちらに、Scalaのソースはこちらになります。

直前で Google翻訳が有料になっていたことが判明したため、急遽 Bing! の翻訳を使うことに。

このテーマでは Scala の特徴でもある関数型プログラミングの親和性を見せられると JRuby や Groovy とうまく差別化できるかな、と思って関数合成を中心に添えています。

ゆろよろさんの「オブジェクト指向プログラマへ捧げる関数型言語への導入」 その1, その2 を参考にさせて頂きました。

mainとなる部分が以下ですね

Console.in :*: read :>: translate :>: addHashTag :>: tweet

:*: も :>: も標準で用意されている apply と compose の別名です。単に左から順に書きたかったのと、合成する対象の関数名と見た目で区別しやすいように記号メソッド名として別名をつけた感じです。

こうすると 標準入力が read に渡って translate に渡って addHashTag に渡って tweet に渡される一連の流れが見たままになってるのが一目瞭然ですね。実は Groovy版もメソッドチェーンを使って同じ流れを表現しようとしていたのが面白かったです。

余談ですが、当初はみんな大好き Twitter4j を使おうかと思ってました。が、実際には Twitter には post するだけで Status の操作も何も行わないため、scalaj-http で実装してしまいました。

Benchmark

もう一つのお題がベンチマークでした。内容は赤黒木のMapを実装してそのパフォーマンスを測定する、というもの。細かいレギュレーションについてはリンク先を参照ください。

Scalaの思想にしたがって immutable版mutable版 の二つを作成しました。immutable版については、以前に Haskell で Purely Functional Data Structures の写経を行っていたためそれほど悩むことなく実装できました。

mutable版は left-leaning red-black tree というアルゴリズムで実装しています。

Groovyのコードが194行、JRubyのコードが195行に対して、Scala版では mutable版が112行、immutable版にいたってはなんと驚きの77行。

コメント行を取り除いてカウントしてもまだ倍近い差があります。動的型の二つの言語では書く必要の無い型情報まで書いてあるにもかかわらずこれだけの差が出るというのは Scala の記述力の高さが示されますねw

(もっとも Groovy版 はパフォーマンスの為に型情報を記述していますが)

(JRuby版 も縦に長いだけで一行の文字数は Scala版 に比べ圧倒的に短いので、文字数で比べると実は大差なかったりします)

そして気になるベンチマークの結果は以下のような感じになりました。

https://docs.google.com/spreadsheet/ccc?key=0AiZsKd8d4hSJdFpaejE4U3pLaUViZHRJQl9RbkFpRXc#gid=1

Groovy++ 圧倒的ですね。さすが。JRubyScala immutable版より若干速いです。

immutable版でメモ化などのimmutableならではの最適化など行えないのか?という疑問を頂いたんですが、レギュレーション的にメモ化が使えるところが少なく効果を発揮するには至りませんでした。地味に height 計算はメモ化というか再計算を行わないようになっているんですが、パフォーマンスの計測では heightの呼び出しを行わない形になっています。

Scala Compiler の理論的には Java とほぼ同じバイトコードが生成できる筈なので Java とこれだけ差がついているのが若干不思議ですね。Java版は一部再帰を使わずにループで処理していたそうで、ちゃんと末尾再帰にしてなかったのが影響してるのかなとも思っています。この辺は機会があれば試してみたいところです。

DSL

最後のお題がDSLです。レギュレーションの詳細はこちらに。

おそらく Groovy版 も JRuby版 も内部DSLで来るだろうなーと思ったので Scala版 では 内部DSL外部DSL の二つを作成しました。

それぞれの使い方を Spec に。内部DSLのSpec, 外部DSLのSpec

実はこれが難産でした。当初はパトリシアトライを模した階層化したデータ構造を作成して、そのデータ構造に変換するDSLを作ったんですが、DSLそのものよりもそのデータ構造の方が複雑になってしまうという結果になってしまった為、素直に HashMap[String, String] を生成する形に変更しました。java.util.Properties への変換は Map[String, String]型であれば何でも変換できるようにして内部DSLと外部DSLで共通化しました。

外部DSLはパーサコンビネータを使っての素直な実装になってます。 properties と nested のように相互再帰な文法もそのまま表現できるところが強いですね。

内部DSLは水島さんからDynamicVariableで現在のコンテキストを表す事で簡潔な表現ができるよというアドバイスを頂いて、DynamicVariableで実現してみました。標準はレキシカルスコープで、必要に応じてダイナミックスコープが使えるというのは非常に便利です。

ちなみに、Groovy や JRuby の実装で使用されている method missing の仕組みですが、Scala にも applyDynamicという仕組みがあり、-Xexperimental オプションを付けることで同じような事が実現できます。

まとめ

という訳でつらつらと書いてきましたが、最後に全体の感想をば。

初っ端からハッシュタグが違うというトラブルから始まり、ほどよく砕けた雰囲気で楽しかったです。各言語の解説もプレゼン自体に特徴がでてて面白かったですし、コーディング大会はナチュラルにdisりあう素敵空間でしたw

ねこはるさんのLTは静的型のScalaならではのもので最後まで皆に見ていただけなかったのは残念でしたね。僕のPCをねこはるさんにお貸ししたのですが、操作しづらかった様で申し訳なかったです><

ゆろよろさんの秘密兵器には爆笑させられました。流石としかいいようがないw 他のLTもみんな高度に笑いを取りに来るのでお腹痛かったですw

そんなこんなでJVM言語BoFはじめJavaOneでは非常に楽しい体験をさせて頂きました。JGGUGの皆様、日本JRubyユーザ会の皆様、ScalaJPの皆様、そして寺田さんをはじめJavaOne Tokyo 2012に関わった全ての皆様へ、心よりお礼申し上げます。