[翻訳] 関数型リアクティブプログラミング(RxSwift-Chinese-Documentation)

中国語で書かれた[RxSwiftのドキュメント](https://beeth0ven.github.io/RxSwift-Chinese-Documentation/)が非常に参考になりました。
他の方のRxSwiftの勉強に少しでも役に立てばと思い、日本語に翻訳してみました！
今回は３章の「関数型リアクティブプログラミング」となります。

原文: https://beeth0ven.github.io/RxSwift-Chinese-Documentation/content/think_reactive.html

## 関数型リアクティブプログラミング

<img width="776" alt="スクリーンショット 2017-12-20 1.06.33.png" src="https://qiita-image-store.s3.amazonaws.com/0/13703/92d7142a-7dc0-6c9c-bd87-62f55e9f9354.png">

関数型リアクティブプログラミング(FRP)はプログラミングパラダイムです。 これは、関数を構築し、それらに応答することによって、データシーケンスを操作するプログラミングの方法です。つまり、リアクティブプログラミングと関数型プログラミングを組み合わせています。

ここで関数型プログラミングを紹介しましょう。

## 関数型プログラミング

![FunctionalProgrammingBanner.png](https://qiita-image-store.s3.amazonaws.com/0/13703/59ba5bce-2a0a-64aa-4543-054131f7bbe0.png)

関数型プログラミングは、関数をパラメーターとして渡す、または戻り値とし返すプログラミングパラダイムです。 さまざまな機能を組み合わせることで、望ましい結果を得ることができます。

いくつかの例を見ていきましょう

```swift
// 全ての学生
let allStudents: [Student] = getSchoolStudents()

// ３年２組の学生
let gradeThreeClassTwoStudents: [Student] = allStudents
    .filter { student in student.grade == 3 && student.class == 2 }
```
私たちは３年２組の学生を取得したいので、３年２組の判定関数を `filter` メソッドに渡しています。これで全ての学生から3年2組の学生をフィルタリングすることができます。

```swift
// ３年２組の男子学生が"一剪梅"を歌う
gradeThreeClassTwoStudents
    .filter { student in student.sex == .male }
    .forEach { boy in boy.singASong(name: "一剪梅") }
```

同様に、性別を判定する関数を `filter` メソッドに渡すことで、3年２組の男子学生をフィルタリングすることができます。そして `forEach` メソッドに歌う曲を関数として渡しています。 だから、すべての男性の同級生は "一剪梅" を歌うでしょう😄。

> 「一剪梅」とは中国の歌のようです。

```swift
// ３年２組の学生から90点以上を取った学生を取得し、その親に賞を渡す
gradeThreeClassTwoStudents
    .filter { student in student.score > 90 }
    .map { student in student.parent }
    .forEach { parent in parent.receiveAPrize() }
```
スコアが90点以上の学生をフィルタリングし、`map`を使用して親に変換します。
最後に、`forEach`を使って各親に賞を渡しています。

```swift
// ３年２組の学生をスコアが高い順に出力する
gradeThreeClassTwoStudents
    .sorted { student0, student1 in student0.score > student1.score }
    .forEach { student in print("score: \(student.score), name: \(student.name)") }
```

並べ替えロジックの関数を `sorted` メソッドに渡しすことで、学生をスコアが高い順に並び替えすることが出来ます。最後に、`forEach` を使用して学生のスコアと名前を出力しています。


関数型プログラミングは、ターゲットの結果を得るために異なるメソッドと異なる機能を組み合わせることができます。従来の for ループを使用して同じロジックを実行するのは退屈です。ですので、関数型プログラミングの利点は明らかです。

- 柔軟である
- 再利用性が高い
- 簡潔である
- メンテナンスが容易
- 様々なニーズの変化に適応

関数型プログラミングの詳細については、[《函数式 Swift》](https://www.objccn.io/products/functional-swift/)を参照してください。

## 関数型プログラミング -> 関数型リアクティブプログラミング

ここでは、関数型プログラミングを使用してシーケンスを操作する方法について書きます。
たとえば、ボタンクリックイベントをシーケンスとして考えようとします。

<img width="475" alt="スクリーンショット 2017-12-20 1.03.13.png" src="https://qiita-image-store.s3.amazonaws.com/0/13703/63454d3e-6e4a-52d4-0a68-1ea3c9bbc5a5.png">

```swift
// ユーザーが3回ボタンをクリックしたとする

// ボタンクリックシーケンス
let taps: Array<Void> = [(), (), ()]

// 各クリック後のAlertView表示
taps.forEach { showAlert() }
```

これはクリックイベントの処理に最適ですが、このシーケンス (クリックイベント) の要素が非同期的に生成されるため、従来のシーケンスではそのような要素の非同期生成を記述できないことが問題になります。
この問題を解決するために、`Observable<Element>` のシーケンスを生成します。このシーケンスの要素は同期または非同期で生成することができます。

<img width="438" alt="スクリーンショット 2017-12-20 1.03.53.png" src="https://qiita-image-store.s3.amazonaws.com/0/13703/2de416e3-2fb7-0868-ade4-cbed0f9e4d9f.png">


```swift
// ボタンクリックシーケンス
let taps: Observable<Void> = button.rx.tap.asObservable()

// 各クリック後のAlertView表示
taps.subscribe(onNext: { showAlert() })
```
`taps`はボタンクリックイベントのシーケンスです。AlertViewの表示は各クリックイベントに応答します。このタイプのプログラミングは、リアクティブプログラミングと呼ばれます。 関数型プログラミングとリアクティブプログラミングに用いることで、関数型リアクティブプログラミングが得られます。

<img width="621" alt="スクリーンショット 2017-12-20 0.50.09.png" src="https://qiita-image-store.s3.amazonaws.com/0/13703/d5575f44-cd17-fa77-e3c3-05b55b643305.png">


```swift
passwordOutlet.rx.text.orEmpty
    .map { $0.characters.count >= minimalPasswordLength }
    .bind(to: passwordValidOutlet.rx.isHidden)
    .disposed(by: disposeBag)
```

様々なオペレーターを使用して、必要なデータシーケンスを作成することができます。
このシーケンスに対応する適切な方法は **関数リアクティブプログラミング** です。

## データバインディング（購読）
<img width="570" alt="スクリーンショット 2017-12-20 0.48.05.png" src="https://qiita-image-store.s3.amazonaws.com/0/13703/cb0ae298-c763-6aa4-d37e-65d9d9f4fa10.png">

`RxSwift` の重要な概念の1つはデータバインディングです。 監視すべきシーケンスがオブザーバにbindされていることを意味します。


次の2つのコードを比較してみましょう。

```swift
let image: UIImage = UIImage(named: ...)
imageView.image = image
```
非常に精通している最初のコードは、ImageView に別の画像を設定しています。

```swift
let image: Observable<UIImage> = ...
image.bind(to: imageView.rx.image)
```

2つ目のコードは、`imageView` にUIImageのシーケンスを "同期" することです。
UIImageのシーケンス は非同期的に生成することが出来ます。
ここで定義されている `image` は、上の画像の青色の部分 (Observableシーケンス)、`imageView.rx.image` は画像のオレンジ色の部分 (Observer)となります。
この "同期メカニズム" をデータバインディング (購読) と言います。

（翻訳が間違ってたら教えてくださいm(_ _)m）