2013年2月20日水曜日

Function Reactive Programming Framework - Reactive Cocoa

Objective-Cで関数リアクティブプログラミングをサポートするライブラリ。


リアクティブプログラミングについてはこのあたりが分かりやすい。


以下、文と図を引用。
リアクティブプログラミングは、「時間とともに変化する値」=「振る舞い」同士の関係性を記述することでプログラミングを行うパラダイムです。
GUIなどのようにインタラクティブなシステムや、シミュレーションやアニメーションのようにダイナミックに状態が変化するようなシステムを宣言的に記述することができます。


よく例えられるのはエクセルのシート。エクセルの場合 セルa1 に b1 + c1 と設定すると b1, c1 の値が変化するにつれて、その都度a1の値が変わっていく。一般的なプログラミングでは a1=b1+c1というのはそのコードが実行された時点での値にしかならない。



このライブラリはObjective-Cでの Functional Reactive Prograamming (FRP)をサポートする。
Reactive Cocoa (RAC) のイメージを掴むには NSHipsterの記事が参考になる。


簡単なコードを例にとって通常のプログラミングとRACの違いが解説されている。

通常のプログラミング例
- (BOOL)isFormValid {
    return [self.usernameField.text length] > 0 && 
            [self.emailField.text length] > 0 && 
            [self.passwordField.text length] > 0 && 
            [self.passwordField.text isEqual:self.passwordVerificationField.text];
}

#pragma mark - UITextFieldDelegate

- (BOOL)textField:(UITextField *)textField
shouldChangeCharactersInRange:(NSRange)range
replacementString:(NSString *)string
{
    self.createButton.enabled = [self isFormValid];

    return YES;
}
フォーム上のテキストフィールドが変更される度に、複数のテキストフィールドが有効かどうかをチェックするというもの。イベントがきたら、チェックを行う(-isFormValid呼び出し)という処理フローを記述する。普通に書けばこんな感じだろう。

RACを使った例
RACSignal *formValid = [RACSignal
  combineLatest:@[
    self.username.rac_textSignal,
    self.emailField.rac_textSignal,
    self.passwordField.rac_textSignal,
    self.passwordVerificationField.rac_textSignal
  ]
  reduce:^(NSString *username, NSString *email, NSString *password, NSString *passwordVerification) {
    return @([username length] > 0 && [email length] > 0 && [password length] > 8 && [password isEqual:passwordVerification]);
  }];

RAC(self.createButton.enabled) = formValid;
一方、RACの場合は処理フローを記述するのではなく、フォーム上のテキストフィールドの値の関係性を記述だけを記述している。関係する複数のフィールドのシグナル(.rac_textSignal)を入力として、値が変化した時にreduce:を実行する定義を1つのシグナル(formValid)として作成し、それをボタンのenabledプロパティと接続する。

こんなイメージ?
username, emailField, passwordField,...のシグナル
     ↓   ↓   ↓ 束ねて1つのシグナル(ただし伝達するのは reduce:の実行結果=評価結果)
     formValid::RACSignal
        ↓ 接続する
     createButton.enabled
シグナルを組み合わせて関係性を記述するようだ。シグナルの伝達はRACが自動的に行う為、KVOを定義する必要はない。一旦関係性を定義すれば後はあとは自律的に動くイメージ(エクセルのシートに似ている)。

NSHipsterではRACとKVOとの比較、Cocoa Bindingsとの比較も出ていた。確かにCocoa Bindingsに近いかな。

***
通常は処理フローを記述し、その中で関係性を評価するのに対して、RACの場合は純粋に関係性だけを記述する。これは今までとかなり考え方が違う(新しいパラダイムと言われる所以か)。

と、今日はここまでの理解で精一杯。正直全体は理解ができなかったが、今までの考え方と違うところが新鮮。とても面白い。これを応用するとオブジェクトの関係性をパラメータ化できるので、GUIツール上でプログラミングレスにある程度の処理が定義できそう(って、それがCocoa Bindingsか)。


(関連情報)





JavaScript用のフレームワーク。サーバを介してデータの更新が伝搬するアイディア。


0 件のコメント:

コメントを投稿