25
23

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

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

Last updated at Posted at 2018-10-14

この記事について

この記事は、Conquering ReactiveSwift: Introductionの翻訳です。

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

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

以下本文です。

ReactiveSwiftを克服する: 導入

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

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

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

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

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

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

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

label.text = textView.text

これは代入する文です。

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

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

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

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

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

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

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

bindingOperator.png
命令型プログラミングとリアクティブプログラミングで"hello"を入力した時の違いを図にして考えてみましょう。
imperativeTimeFlow.png
命令型のやり方では、変わりゆく状態という観点からシステムを設計します。たとえば、上の図では、それぞれの文字の入力を関知して、その都度labelの状態を更新しています。

reactiveTimeFlow.png

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

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

便利な用語

関数型HaskellプログラマのHeinrich Apfelmusは、上で議論してきた考え方を二つの文に要約しています。

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

次回は、、、

この記事でFRPに対するモチベーションが湧いたでしょうか?サンプルコードはこちらからダウンロードすることができます。次の記事では、ReactiveSwiftの基本について議論します。

シリーズ内リンク集

  1. この記事です
  2. ReactiveSwiftを克服する: 基本要素 (Part 2)
  3. ReactiveSwiftを克服する: SignalとObserver (Part 3)
  4. ReactiveSwiftを克服する: SignalProducer (Part 4)
  5. ReactiveSwiftを克服する: Property (Part 5)
  6. ReactiveSwiftを克服する: Action (Part 6)
25
23
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
25
23

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?