ReactiveSwiftを克服する: 導入 (Part 1)

## この記事について

この記事は、[Conquering ReactiveSwift: Introduction](https://medium.com/fueled-engineering/reactive-programming-introduction-to-reactiveswift-c3fcef5e896)の翻訳です。

翻訳しても問題ないか著者さんにTwitterで聞いてみたところ快く了承していただきました。

<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">Hey Takanori, I am so glad that you found this useful. Of course, you can translate and share.</p>&mdash; Susmita Horrow (@SusmitaHorrow) <a href="https://twitter.com/SusmitaHorrow/status/1047871906844696577?ref_src=twsrc%5Etfw">October 4, 2018</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

記事本文中にもありますが、この記事は全6回シリーズの最初の記事です。次回以降の記事も翻訳して投稿する予定です。

以下本文です。

# ReactiveSwiftを克服する: 導入

> リアクティブプログラミングの学習曲線は急峻だ

私が関数型リアクティブプログラミング(Functional Reactive Programing, FRP)を学習していたとき、よくこの言葉を耳にしました。命令型プログラミング畑出身だった私は、FRPのいろいろな概念を理解するために奮闘しました。**FRPの最も重要な利点は、時間の経過のモデル化が容易になるところです。**しかし、これは簡単には理解できないこともあります。みなさんが学習の最初の一歩を踏み出す助けになればと思い、「ReactiveSwiftを克服する」と題したシリーズで私の理解を共有します。ReactiveSwiftについて初心者にもわかるように少しずつ案内することを目標としています。

この記事はシリーズの最初の記事です。ここでは、関数型リアクティブプログラミングについて紹介し、命令型プログラミングとの違いを明らかにします。

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

この2つの枠組みの違いを理解するために、次のようなUIを考えてみましょう。**UILabel**(`label`と呼びましょう)と**UITextView**(`textView`と呼びましょう)があって、`label`には`textView`に入力されたテキストが反映されるとします。この振る舞いを実装するには、こう書きます:

```swift
func textViewDidChange(_ textView: UITextView) {
    label.text = textView.text
}
```

上のコードはちゃんと動きます。私達はずっとこうやってきました。なにが問題でしょうか？もう少し考えてみましょう。`label`のテキストを更新するための文はこうです:

`label.text = textView.text`

これは代入する文です。

これの意味はなんでしょうか？これは、代入の瞬間において`label.text`が`textView.text`と等しくなることを意味します。この文は代入の前後の`label.text`の値については何も関知しません。つまり、*「 `label.text`は`textView.label`と等しい 」*という命題は、時間の経過を考慮に入れると、必ずしも真であるとは言えなくなるのです。

したがって、私たちはこの文を`textViewDidChange`というデリゲートメソッドの中に書くことで`label.text`の値を維持します。命令型プログラミングではこのような関連性をエレガントに書くのは非常に難しいです。

### リアクティブバインディングへようこそ

リアクティブプログラミング( *とりわけ、* ReactiveSwift)では、バインディングでこの問題を解決することができます。

**`label.reactive.text <~ textView.reactive.continuousTextValues`**

この文は`label`のテキストが`textView`のテキストと`label`が存在している間ずっと等しくなることを示します。

目新しいものに気づきましたか？ `<~`は**バインディング演算子**と呼ばれるものです。演算子の左辺にあるのは**バインディングターゲット**で、右辺にあるのは**バインディングソース**と呼びます。「ReactiveSwiftを克服する」シリーズでは以降の記事でこの文を深掘りします。

![bindingOperator.png](https://qiita-image-store.s3.amazonaws.com/0/130238/010da54c-76d6-c1d1-c8a1-957e32bb3b5d.png)
命令型プログラミングとリアクティブプログラミングで"hello"を入力した時の違いを図にして考えてみましょう。
![imperativeTimeFlow.png](https://qiita-image-store.s3.amazonaws.com/0/130238/1a7e486d-943f-9b6d-41d4-1cbc6201600d.png)
命令型のやり方では、変わりゆく状態という観点からシステムを設計します。たとえば、上の図では、それぞれの文字の入力を関知して、その都度`label`の状態を更新しています。

![reactiveTimeFlow.png](https://qiita-image-store.s3.amazonaws.com/0/130238/2bceaf73-ba72-3f1c-63fb-5cc737916e65.png)

FRPでは、システムをイベントのストリーム(流れ)に応じた振る舞いという観点から設計します。上記の例では、テキストの入力というストリームに応じた`label`の振る舞いを定義しています。テキスト入力という個々のイベントに対する状態の更新について関知していません。

リアクティブプログラミングのメリットは他にもあります。それは`label`の振る舞いが宣言の時点で明確になっていることです。対して、命令型プログラミングでは制御ロジックがあちこちのデリゲートメソッドに散らばってしまいます。長い目で見ると、振る舞いの理解が難しくなっていきバグの起こりやすいコードになりかねません。

## 便利な用語

関数型HaskellプログラマのHeinrich Apfelmusは、上で議論してきた考え方を[二つの文に要約](https://apfelmus.nfshost.com/blog/2011/03/28-essence-frp.html)しています。

> - 意味論的には、FRPは、変化していく状態の代わりに時間変化する関数を使ってシステムを記述します。
> - 統語論的には、FRPは、宣言の時点で値の動的な振る舞いを完全に決定します。

## 次回は、、、

この記事でFRPに対するモチベーションが湧いたでしょうか？サンプルコードは[こちら](https://github.com/hsusmita/conquering-reactive-swift/blob/master/ConqueringReactiveSwift/Paygrounds/Conquering-Reactive-Swift.playground/Pages/Introduction.xcplaygroundpage/Contents.swift)からダウンロードすることができます。次の記事では、ReactiveSwiftの基本について議論します。

### シリーズ内リンク集

1. この記事です
2. [ReactiveSwiftを克服する: 基本要素 (Part 2)](https://qiita.com/taka1068/items/9e6ccce4297832817444)
3. [ReactiveSwiftを克服する: SignalとObserver (Part 3)](https://qiita.com/taka1068/items/bdd0329202cea0e0c4b6)
4. [ReactiveSwiftを克服する: SignalProducer (Part 4)](https://qiita.com/taka1068/items/85211855bcee06e18566)
5. [ReactiveSwiftを克服する: Property (Part 5)](https://qiita.com/taka1068/items/fcde158848dbe3169477)
6. [ReactiveSwiftを克服する: Action (Part 6)](https://qiita.com/taka1068/items/9ea40476076623c2a910)