Scalaの綺麗な書き方（メモ用）

自分用のScala書くときのメモ。

# Optionの扱い方
一番詳しいページ：http://scalamanual.blog.fc2.com/blog-category-14.html
 
 - OptionのNoneの処理は、 getOrElse で書ける。
 - foldで、Noneの時のデフォルト値を設定できる。

以下3つ全部一緒の処理。この3つならmapでいいかと。

```scala
aOpt.map(_ > 10).getOrElse(true)
```

```scala
aOpt match {
  case None => true
  case Some(a) => a > 10
}
```

```scala
aOpt.fold(true){_ > 10}
```

## パターンマッチを回避してOptionを処理する
Optionの値がSome(a)の時だけ続きの処理を行うにはmap, foreachを使う

```scala 
val m = Map("A" -> "Apple", "B" -> "Banana") 
val b = m.get("A").map{_.length} // 戻り値を使用
m.get("A").foreach{printf(_)} // 戻り値を返さない
```

## boolean 値を帰す場合
boolean値を返す場合、existsやforall　等も使う事が出来る。 存在確認のcontainsもよく使う。

```scala
aOpt.exists(_ > 10)
aOpt.forall(_ > 10)
```

他、参照→ http://qiita.com/mizuki0420@github/items/ac7a6850aa3479ebc906
 

# FlatMapの便利な使い方
1, mapにヒットしない時に、orElseを使って、後続の処理を書ける

```scala
val id = dog.map(_.id).getOrElse(cat.fold(None){_.id})
```

のようにOptionを返すような場合、flatMapを使うと、

```scala
val id = dog.flatMap(_.id).orElse(cat.flatMap(_.id))
```

とシンプルに書ける。

http://qiita.com/mtoyoshi/items/c95cc88de2910945c39d がちょう詳しい


# 複数のOptionがNoneじゃない時だけ処理する

```
val response = for {
    i1 <- iOpt1
    i2 <- iOpt2
} yield {
    i1 + i2
}
```

のようにfor yieldを使うと良い。
実はこれ超便利で、mapとflatMapが入り乱れたものを完結に書くことが出来る。
`i1.isDefined` が `true` のときのみ、i2,i3...の処理が実行されるため、mapチェーンを完結に書くのに優れている。

例えば、以下の二式は同じ処理を行う。

```
people.flatMap(p =>
  addresses.filter(a => p.addressId === a.id)
           .map(a => (p.name, a.city))
).result
```

```
(for {
  p <- people
  a <- addresses if p.addressId === a.id
} yield (p.name, a.city)).result
```



# 例外処理
 - Try match 文で Success Failureに分けて書く

```scala
Try(...) match {
  case Success(a) => ...
  case Failure(e) => ...
}
```

- Failureの処理だけしたい場合は、recoverを使うとエラーハンドリング処理だけシンプルに書ける。

```scala
Try(...).recover{ case e:Exception =>
  log.error(e)
}
```
 
# for の使い方
複数のTryの結果より正常処理とエラー処理を分ける場合はforを使うと良い。
http://tersesystems.com/2012/12/27/error-handling-in-scala/

```scala
val sum = for {
  int1 <- Try(Integer.parseInt("one"))
  int2 <- Try(Integer.parseInt("two"))
} yield {
  int1 + int2
} recover {
  case e => 0
}
```

# 可変長引数に展開する
Seq(...) : _* で展開できる
 
http://etc9.hatenablog.com/entry/20100519/1274285392

# Mapのcaseの使い方
Mapをのkeyとvalueを反転したい時は、 case を使えば良い。
 上のMapとkeyとvalueが反対になる。

```scala
private val AToBMap: Map[A, String] = BToAMap.map { case (key, value) => (value, key)}
```
 
# PHPの var_dump()っぽいもの
 - http://d.hatena.ne.jp/tonfabeem/20131110/1384044294

```scala
import scala.runtime.ScalaRunTime._
println(stringOf( Array(1,2,3) ))  // => Array(1, 2, 3)
```

Arrayではない適当なオブジェクトも、人が読める程度に出してくれた

# Scala Collection Method
演算子系はこのページが一番詳しい
http://www.ne.jp/asahi/hishidama/home/tech/scala/collection/method.html
 
# 引数の事前チェック
if文でパラメータの引数チェックしてIllegalArgumentException 投げるくらいならrequireを使え。
 - http://d.hatena.ne.jp/kaoskfos/20120401/p1

```scala
scala> def foo(a: Double, b: Double) = { require(b != 0); a / b }
foo: (a: Double, b: Double)Double
scala> foo(5, 2)
res0: Double = 2.5
scala> foo(4, 0) ←エラーになる
java.lang.IllegalArgumentException: requirement failed
        at scala.Predef$.require(Predef.scala:145)
``` 


# テスト関連
## there was one で、引数を「a」に指定したいとき

```scala
there was one(mockClass).(===(a))
```

## class A を継承して、Bをprotectedから外したいとき 

```scala
TestA extends A {
   override def B = super.B
}
``` 

## 型をテストしたいとき
beAnInstanceOfを使う

```scala
cat must beAnInstanceOf[Animal]
```