Scala 事始め、あるいは新しい言語の勉強方法

ご存知かとは思いますが、これまで仕事場では皆様のツイートと呼ばれる140文字程度の投稿を読んで適切なタイムラインに仕分けしたり、ハッシュタグを見て検索結果に追加したりとなかなか骨が折れる作業をしていて、随分慣れてきたのですが、どうしても最近はじまった「60秒でツイートを届けるキャンペーン」で間に合わないことが多く、中にはUnicodeの合字を組み合わせた塩抜きポテトみたいなツイートも多く、一部、Ruby を使って自動化したりしてみたのですが、そろそろ体力の限界を感じていたところでした1

そんな折、同僚が、「オレ、Scala を使ってるんだけど肩こりも治ったし、60秒キャンペーンも余裕だよー」って言ってるのを聞いて、そんなにいいなら、とちょっと使ってみることにしました。

新しい言語を覚える

実際のところ、仕事場ではかなり前から Scala で書かれたプロジェクトがありましたが、この公開されているレポジトリを見てもわかると思うのですが、その数はどんどん増えています。 というか、Scala と Ruby だけじゃなくて、Clojure あり、English あり、JavaScriptあり、Python あり、と使用される言語は増えるばかりなわけで新しい言語を覚える機会は結構あります。

そんな中で Scala の雰囲気やコードに触れる機会はけっこう多かったのですが、ふとした瞬間に現れる悪魔のような言語の片鱗が怖くて今日までまじめに勉強することはありませんでした。しかし、そうも言ってられないので、アメリカでは珍しい3連休を費やして集中して勉強したのでその方法をメモしておきたいと思います。

眠い教科書は最初に見ちゃダメ

新しいことを覚えるのはいつも手探りです。Scala については過去に買った教科書的な本が手元にあったのですが最初の10ページ読んで眠たくなって、ついに読むことはありませんでした。どうやら、眠たくなる理由は次のようなものと思われます。

ひとによっては教科書的な本が合う人もいると思いますが、どうしても僕には合いませんでした。 それよりも、実際に使われている、かっこ良いとされるコードがどうしてかっこ良くて、それがどうやって動いているのかを知っていくほうが楽しかったのです。

そこでまず使ったのは

です。

一番最初にやったこと

次のコードは Scala の Hello world です。最初にやったことは、この1行目の意味を理解することでした。 object ってなんやねん、と。

object HelloWorld {
  def main(args: Array[String]) {
    println("Hello world!")
  }
}

僕がこの時点で既に持っていた知識は、Scala は Java VM で動くということです。当然、この Hello world を scalacでコンパイルすると class ファイルが出てきます。しかも、2つも。

そこで取り出したのが、javap です。

$ javap -c -private HelloWorld
public final class HelloWorld extends java.lang.Object{
public static void main(java.lang.String[]);
  Code:
   0: getstatic #16; //Field HelloWorld$.MODULE$:LHelloWorld$;
   3: aload_0
   4: invokevirtual #18; //Method HelloWorld$.main:([Ljava/lang/String;)V
   7: return

}

として、ははーん、なるほど、それで HelloWorld$.class が出来たわけかと思ったわけです3。そこで再び javap をして実際にobjectが何なのか、なぜ Singleton になりうるのかということを理解しました。

このようにして、HelloWorldvalvardef あるいは classtrait を書いてみて、たまに scala REPLを使って細かなコードの挙動を調べたり、なんか見たことあるな、みたいな Scala のコードが実際どういう動きをするのかを理解していきました。

この時点で大まかな言語仕様については理解してだいぶ楽しくなってきたのですが、まだ魔法のような Scala のコード4をすべて読めるようにはなりませんでした。

次にやったこと

この辺りで1日使ったので、次の日はひたすらドキュメントを読みました。日本語で書かれてるものはやはり速く読めるので優先的に読んで、謎な部分は scala-lang.org のリファレンスを見つつ、たまに気になるところは scala REPL や javap を使ったりしてわりと網羅的に英単語を覚えるように進めました。

しかし、まだよくわからない魔法のようなコードはあったのです5

より理解を深めるために

この辺りで2日つかったので、連休最後の日は過去に10ページ読んで寝てしまった教科書的な本やPDF的なやつを読みました。 これまでの2日間で基礎体力はバッチリだったので眠いコレクションの話もなんとか耐えることができるレベルまで到達することができました。

しかし、つい猫画像とか見てニヤニヤしたり、PDFを読むにあたって、iPad 重い、iPad mini 欲しい欲しい、でもRetinaじゃないしー、とか思って Apple Store に行っちゃいそうになったりしてたのであまりちゃんと読んでなかった気もします。

とそんな感じで3連休が過ぎ去りついに平日がやって来ました。

実践投入

先にも書いたとおり、仕事場での作業は一部 Ruby で自動化していたのですが、それでも140文字とはいえ世界中から届く投稿を読んで仕分けする作業はとても大変だったのでした。しかし Scala を実践投入した初日から、なんと、悩みのたねだった肩こりが治りはじめ、メキメキと仕事が捗るではありませんか!!

まじめに勉強を初めて3日だったのですが、詳しく挙動を javap などで追ったことが幸を奏したのでしょう。60秒サービスで作ったハンバーガーのような Scala コードの問題も見つけられるレベルに!

と、まあ、その後数日で悪魔のような言語に慣れた人が書いたとおもわれるようなコードに悩みながらも、周りの Scala の先輩に聞いたり、既存のかっこいいコードを読んだりしながらかなり良い感じでコードがかけるレベルになりました6

まとめ

というわけで、新しい言語やツールの使い方を覚えるときは、

という感じで進めるといいかなー、と思います。

  1. 多分、規模的に Twitter は世界最大級の Ruby アプリケーションでした。 ↩︎

  2. REPL = Read–Eval–Print Loop の略。irb みたいなやつ。 ↩︎

  3. Singleton の実態である HelloWolrd$ クラスを呼び出しているだけの存在です。 ↩︎

  4. Option(x) getOrElse Option(y).filter(_.f).map(_.g).getOrElse(z) みたいなコード ↩︎

  5. def f(a:A, b:B)(implicit c:C) = { … } みたいなコード ↩︎

  6. とはいってもまだまだ全然なのでご教授のほどよろしくお願い致します。 ↩︎