読者です 読者をやめる 読者になる 読者になる

Scala勉強会に行ってきた

こんばんは、south37です。今日は芸者東京エンターテインメントさんが主催するScala勉強会に行ってきました。いろいろなところでScalaの名前を聞いて興味を持っていたところにアカリクさんからイベントの案内が来て、ちょうどいい機会だと思いふらっと行ってきた感じです。

ざっくりとではありますが、勉強会の様子とScalaに抱いた感想をまとめてみたいと思います。

ちなみに、講師の方もはてなブログ書いたっぽいです

「すぐやれる Scala」 - 次世代の開発言語を学ぶ1日 -

これが勉強会のタイトルです。内容としては、芸者東京さんがScalaを使って作ったTwitterクライアントのひな形アプリを用意してくれていて、それをgit cloneしてきて適宜書き換えて遊んでみよう、みたいな感じでした。あえて機能が足りない感じで作ってあり、それを補完して完成度を高めて行きます。フレームワークとしては、Play Frameworkが使われていました。

進行の様子

JDKやSBTのインストール、Twitterのdeveloper登録が事前課題(?)だったのですが、けっこうやってきてない人も多くて、スタート地点が人によってバラバラでした。

Twitterのdeveloper登録がモバイル登録必須になっていたりとトラップが多くて、そこで進行がちょっと遅れたりしてました。足並みを変に揃えずに各自マイペースに進めて、分からない事があれば適宜その辺を歩いてるメンターさんに聞くってスタンスで、僕としてはやりやすかったです。

Play Frameworkの印象

Play Frameworkは名前だけは知っていたのですが、使ったのは初めてでした。MVCベースで、conf/routesでルーティングを指定していて、railsっぽさを感じました。 すごいと思ったのはファイルを更新すると自動でコンパイルされる点で、改良してブラウザで確認してってのがスムーズに行えてやりやすかったです。コンパイルが必要な言語を使っているという事をほとんど意識しませんでした。

Scalaについて

Scalaを触ったのは初めてだったのですが、普段スクリプト言語ばっか触ってる自分からしても取っ付き易かったです。

簡単に特徴をまとめてみると、

  1. オブジェクト指向と関数型のハイブリッド
  2. 型推論が強力でさくっと書ける
  3. JVM上で動く

みたいな感じでしょうか。全体として、いろんな概念のいいとこ取りをしているように感じました。

オブジェクト指向と関数型のハイブリッド

Scalaオブジェクト指向っぽくも関数型言語っぽくも書けます。より正確には、ベースはオブジェクト指向言語なのですが、関数型言語の良さげなパーツをいろいろと取り入れています。

変数

例えば、scalaでは変数の宣言にはvalまたはvarを使います。その時、valで宣言した場合には再代入が許されません。

var str = "str1"
str = "str2" // varで宣言した変数は再代入可能

val str = "str1"
str = "str2" // error: reassignment to val

これは、前回紹介したようにHaskell等で変数が再代入出来ない事を真似ているのだと思います。代入ではなく宣言を用いるという関数型っぽさを取り入れている訳です。

関数が第一級オブジェクト

また、scalaでは関数が第一級オブジェクトです。どういう事かと言うと、関数を引数として受け取ったり、変数にbindしたり出来ます。

例えば、以下のようなコードが書けます。

val square = (x :Int) => x * x

これは、ラムダ式を用いて無名関数を作り、それをsquareという名前の変数にbindしています。ラムダ式は、=>の左側に引数を書いて=>の右側に返り値を書く事で無名関数を作る事が出来る構文で、上記の例ではInt型の引数を受け取ってその二乗を返す無名関数を定義しています。val square =で、その無名関数をsquareにbindしている訳です。

map関数などは、関数を引数としてうけとります。無名関数を渡す事もよくあり、例えば下記のようなコードが書けます。

val list = List(1, 2, 3).map(x => x + 1)
println(list) // List(2, 3, 4)

パターンマッチング

関数の定義や変数の宣言の際に、パターンマッチングを用いる事が出来ます。

num match {
  case _ :Int    => println("Int型")
  case _ :Long   => println("Long型")
  case _ :Double => println("Double型")
  case _         => println("それ以外の型")
}

上記の例では、numの型がIntLongDoubleかそれ以外なのかで処理を分けています。構文としては、変数 match {ブロック}という形になります。型だけでなく、値そのものの一致や値の一部の一致など柔軟に条件を設定出来るため、かなり強力な機能になります。ガード条件(if)を用いる事も出来ます。

num match {
  case x :Int if x > 100 => println("100より大きなInt型")
  case x :Int            => println("Int型")
  case _                 => println("それ以外")
}

また、matchは式である為、値を返します。具体的には、マッチしたパターンの=>の右側の値が返る為、変数の宣言にも用いる事が出来ます。

val message = (tweetsCount % 3) match {
  case 2 => stupidMessage
  case _ => defaultMessage
}

これは今回の勉強会で書いたコードの一部なのですが、tweetsCountが3で割って余りが2であればmessageにはstupidMessageが代入され、余りが01であればdefaultMessageが代入されます。

抽出子(Extractor)によるパターンマッチ等、パターンマッチはもっともっと奥深いみたいですが、とりあえず説明はこのへんまでにしておきます。

Scalaにおける型推論

ここまでのコードを見てきて気がついた方もいらっしゃると思うのですが、scalaにおいてはそれほど型を書く必要がありません。それは、強力な型推論機構を持っているからです。

型推論というのは、変数や関数の型を宣言しなくても自動的に型を決定する機構のことです。例えば、

val str = "str"

というコードを考えた時、strという変数には文字列リテラルによって生成された文字列"str"がbindされている為、strの型はStringであるという事が確実となります。その為、わざわざ

val str :String = "str"

という風に型を宣言しなくても、コンパイラは型を判別する事が出来ます。これが型推論です。

多くの場合、関数の返り値の型は書かなくても型推論が行われます。逆に、引数の型は関数の定義時には推論出来ないため、基本的には書く必要があります。

ちなみに、メンターさんには返り値の型も出来るだけ書いた方が良いよって言われました。確かに、ちゃんと意図したものが返ってきてるかを確かめたい時は、型を書いた方が良さそうです。

型推論があるおかげでわずらわしい型の宣言から解放され、スクリプト言語のようにサクサクとコーディングが出来ます。素晴らしいですね!!!

ScalaJVM上で動く

scalaバイトコードコンパイルされた後、JVM上で動きます。その為、Javaと非常に相性が良く、Javaの多くの資産を使う事が出来ます。実際、勉強会中はJavaDateクラス等を使うコードを書いていました。

自分は普段Javaを書かないのでこのへんはあまりピンと来ないのですが、Javaの資産を多く抱えている人に取っては、scalaというのはかなり魅力的な選択肢になるんんじゃないかと思います。

まとめ

Scalaは良さげだったので触ってみるといいと思います。特に、普段Java書いてるけどめんどくせって思ってる人。

追記: どうでもいい話

勉強会中、芸者東京の人がやたら「もうJavaは書きたく無い」って連呼してたのが印象的でしたw