Scala の Future

# Scala の Future
## 前提
- ぼくJavaもScalaも詳しくないです

## 参考
- 本家 https://docs.scala-lang.org/ja/overviews/core/futures.html
- コップ本 https://www.amazon.co.jp/Scala%E3%82%B9%E3%82%B1%E3%83%BC%E3%83%A9%E3%83%96%E3%83%AB%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E7%AC%AC3%E7%89%88-Martin-Odersky/dp/4844381490/ref=sr_1_sc_1?ie=UTF8&qid=1507823541&sr=8-1-spell&keywords=scalaa

## Futureとは
- Scalaで非同期処理を扱うためのもの
- 処理をブロックすることなく、結果の値を処理、合成できる
- 非同期で行われる処理が`完了`すると`成功`または`失敗`が値で表現される

## 背景
- Javaで提供されているマルチスレッドによる制御は`共有データ`と`ロックモデル`で並行処理を実現する
- ロックと共有モデルはデッドロックのリスクと戦ったりとなかなか難しいのだ
	- 頑張って実装すれば共有データとロックを隠すことはできるだろうが‥
 - 難しいというものの、`java.util.concurrent`を使えばスレッドを生で扱うよりは優しい
- この難しさに対してScalaのFutureは`共有データ`と`ロック`についてあまり考えず並行処理を実現できる

## 背景を踏まえた上で
- Futureも中身的にはマルチスレッドによる非同期処理
- Futureを利用する上でスレッドを意識することは(あんまり)ない
	- Futureとして定義した処理が`どのスレッドで実行されているか`を利用者が意識しなくていい

## 使ってみた

### 簡単に非同期処理されているのがわかる

```
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global // おまじないです *1

Future { // Future.applyに渡したブロックが非同期で処理される
  for (i <- 5 to 10) {
    Thread.sleep(1)
    println(s"${i}: in Future")
  }
}

for (i <- 0 to 4) {
  Thread.sleep(1)
  println(s"${i}: in Main")
}
```

```
5: in Future
0: in Main
6: in Future
1: in Main
7: in Future
8: in Future
2: in Main
9: in Future
3: in Main
10: in Future
4: in Main
```

- 出力が`in Future`と`in Main`で入り乱れているのがわかる

### `完了`すると`成功`、`失敗`を値として表現
- Futureの`onComplate`では完了した結果を引数にしたコールバックを渡せる
- コールバックの引数になるのは`Future[T]`に対して`Try[T]`
	- `T`はFutureが成功したときの結果の型
	- `Try[T]`は`Success`または、`Failure`になる。
		- `Success`のときは`T`の値を持ち、`Failure`のときは`Exception`を持ち、失敗の理由がわかる

```
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global // おまじないです *2

val successFuture = Future[Int] { 100 }

val failFuture = Future {
	throw new RuntimeException("失敗じゃ")
}

successFuture.onComplete { // Futureの完了時にコールバックを渡せます
	case Success(intValue) => println(s"future success: ${intValue}")
	case Failure(_) => sys.error("ここに来ることはないだろう...")
}

failFuture.onComplete {
	case Success(_) => sys.error("ここに来ることはないだろう...")
	case Failure(exception) => println(s"future fail: ${exception}")
}
```

```
future success: 100
future fail: java.lang.RuntimeException: 失敗じゃ
```

- onCompleteで`成功`、`失敗`のケースが明確に書き分けられる！

## 結果をブロックすることなく処理する
- Futureは`map`,`flatMap`,`foreach`等が使えて非同期で渡って来る値を難しいことせずに扱える
	- `filter`,`collect`...紹介しきれないほど便利な奴らがあるぞ！
	- 便利な奴らを紹介してくれる良記事 -> https://qiita.com/mtoyoshi/items/f68beb17710c3819697f

```
val intOneFuture = Future { 1 }

def intToStringF(value: Int): Future[String] = Future { s"int: $value" }

intOneFuture.map(_ * 100).flatMap(intToStringF).foreach(println)
```

```
int: 100
```

## まとめ
- Futureを使うとスレッドをあんまり考えなくてもいいっぽい
- Futureを使うと簡単に非同期処理が実現できる
- Futureを使うと非同期処理の結果の値を簡単に処理できる

## *1, *2  おまじないです
### なぜ必要か
- `import scala.concurrent.ExecutionContext.Implicits.global`
- `Future.apply`が`ExecutionContext`としてimplicitで必要としている

### `ExecutionContext`とはなにか
- Futureに渡されたコードブロックを実行する仕組みを提供するもの
- 非同期であるというのは実装によるものでやろうと思えば同期的なFutureも作れちゃう 
- `import scala.concurrent.ExecutionContext.Implicits.global`はScalaが提供しているExecutionContextの実装の一つ
	- Scala 2.12ではJavaのForkJoinPoolという実装を利用して実現しているらしい..