社内scala勉強会#3まとめ

今の会社内でScala勉強会が開催されてるのでまとめ。
twitterから公開されているScala Schoolを使っています。
http://twitter.github.com/scala_school/

今回はCollectionsの前半。
http://twitter.github.com/scala_school/collections.html
以下のコードの引用はほとんどScala Schoolのものです。

バックナンバー

#1 @satococoaさん
http://www.223soft.net/56
#2 @netwillnetさん
http://d.hatena.ne.jp/willnet/

Lists

ふつーに配列

val numbers = List(1, 2, 3, 4)
numbers: List[Int] = List(1, 2, 3, 4)

Sets

重複しない配列。JavaのListとSetの関係と同様

scala> Set(1, 1, 2)
res0: scala.collection.immutable.Set[Int] = Set(1, 2)

Tuple

これはあんまり見ない概念でした。
何が配列と違うんや!と思ったし、実際機能上はほぼ変わらない。
色々いじって調べた結果、配列は「複数の同じ種類のモノを格納」に対し、タプルは「複数の値で表現される一つのデータを格納」するっぽい。
それクラスでできんじゃね?とも思いますが、Javaでデータだけ入れるちょっとしたクラスを作るシチュエーションを想定してるようです。
他で調べた結果、タプルの2値限定はPair、3値限定はTripleという別名があるらしい。

scala> val hostPort = ("localhost", 80)
hostPort: (String, Int) = (localhost, 80)

まあわかってからこの例を見れば一目瞭然。

scala> hostPort._1
res0: String = localhost
scala> hostPort._2
res1: Int = 80

アクセスするには「_n」というアクセサを使用。

hostPort match {
  case ("localhost", port) => ...
  case (host, port) => ...
}

パターンマッチにも使える。便利そう。

scala> 1 -> 2
res0: (Int, Int) = (1,2)

こういう書き方もある。要素一個のMapっぽい。

Maps

JavaのMap、Rubyではhash。

Map(1 -> 2)
Map("foo" -> "bar")

=>はFunctionに取られてるのでC言語でおなじみアロー演算子を使うらしい。

Map(1 -> Map("foo" -> "bar"))
Map("timesTwo" -> timesTwo(_))

マップの中にマップもアリ。
後者はどうやっても動かなかったので

Map("timesTwo" -> timesTwo _ )

の誤記じゃないか?という結論でした。
Functionの部分適用も入るよーということ。まあ要は何でも入ると。
ちなみに

val m = Map("key" -> "value" )
m.get("key")

した結果はvalueではありません。後述のOptionです。

m.get("key").get

で"value"が取得できます。

Option

で、Option。Optionはこんなtraitのようなモノ…らしい。

trait Option[T] { def isDefined: Boolean def get: T def getOrElse(t: T): T }
scala> val numbers = Map(1 -> "one", 2 -> "two")
numbers: scala.collection.immutable.Map[Int,String] = Map((1,one), (2,two))
scala> numbers.get(2)
res0: Option[java.lang.String] = Some(two)

値があるときはSome

scala> numbers.get(3)
res1: Option[java.lang.String] = None

値が無いときはNone
が返る。
Some[T]とNoneはOptionのサブクラス。

val result = if (res1.isDefined()) { res1.get * 2 } else { 0 }

こんなときや

scala> numbers.get(3).getOrElse("default")
res6: java.lang.String = default

こんなときもぬるぽを心配せずに書けるよ!

まとめ

私はJavaが一番長いので、ああ、Javaでめんどくせーところを簡単にできるようにしてあるな、ってのが今回の印象でした。
CほどじゃないにしてもJavaのぬるぽチェックはめんどくさいし、2値のセットを入れるためにcommonsライブラリのPairクラス使ったりしてたので。
とはいえ、Optionあたりはぬるぽチェックのためだけじゃなくて、後半のmapとかfilterとかの関数型っぽい機能を簡潔に書くための機能でもあるんだと思います。
Scala School、1ページ目からカリー化とか部分適用とかかなり難解でしたが、今回は実用的でわかりやすかったと思う。