FRPライブラリを作ってわかった、FRPの意味と意義


FRPライブラリを一日かけて作ってて思いました。これはメインループの復権だ！！
例のごとくまさかりよろしくです！！

--

頭の体操をしましょう！！

FRPライブラリである、Bacon.jsの例題を引用します。
https://baconjs.github.io/tutorials.html

* Username availability checking while the user is still typing the username
* Showing feedback on unavailable username
* Showing an AJAX indicator while this check is being performed
* Disabling the Register button until both username and fullname have been entered
* Disabling the Register button in case the username is unavailable
* Disabling the Register button while the check is being performed
* Disabling the Register button immediately when pressed to prevent double-submit
* Showing an AJAX indicator while registration is being processed
* Showing feedback after registration

雑に日本語に訳します。

* usernameが使えるかどうかリアルタイムでチェック
* usernameが使えないなら通知する
* チェックを行っている最中インジゲータを表示
* 登録ボタンはusernameとfullnameが入力されるまで無効化
* usernameが使えないなら登録ボタンは無効化
* 二重登録を避けるためにクリックされたら即座に無効化
* 登録処理中はインジゲータを表示
* 登録処理がおわったら通知する

んん？余計わかりにくくなった気がしますね……プログラム書きならコードで語るのだ＠v＠！！
CoffeeScriptっぽい疑似コードで書きましょう。

```coffee
available = (name)->
	showIndicator()
	result = checkAvailableAjax(name)
	hideIndicator()
	result

processRegistration = (user, full)->
	showIndicator()
	registerAjax(user, full)
	hideIndicator()
	
check = ()->
	disableButton()
	unless available(@username)
		feedbackUnavailableUsername()
	else if @username and @fullname
		enableButton()
		return true
	return false

register = ()->
	disableRegisterButton()
	processRegistration(@username, @fullname)
	feedbackRegistraction()
```

おお、なんか簡単そうですね！！
しかし！！！非同期の魔物が待ち受けています！！これをまともに組んだらうん１０倍くらいに膨れ上がるでしょう。（気になった方だけ実装してください……）

しかしです、拙作のライブラリを使えばこのようになります。


```
available = ($)->
  $(showIndicator)()
  result = $.async(checkAvailableAjax)($.username).get()
  $(hideIndicator)()
  result

processRegistration = ($)->
  $(showIndicator)()
  $.async(registerAjax)($.username, $.fullname).get()
  $(hideIndicator)()

form.on.keydown = ($)->
  $(disableButton)()
  unless available($)
    $(feedbackUnavailableUserName)()
  else if $.username and $.fullname
    $(enableButton)()
    return true
  return false

form.after.keydown = (value)->
	form.checkResult = value

form.on.register = ($)->
  unless $.checkResult
    return false
  $(disableButton)()
  processRegistration($)
  $(feedbackRegistration)()
  return true
```

なんということでしょう、疑似コードとあまり変わらないではないですか！！
あとは各々の関数に対して、実装していくだけですね。

# 秘密はFRP

これはBacon.jsと同じく、FRPと呼ばれるパラダイムに基づいています。
FRPの説明の前に、Reactiveであることからです。

## Reactive Programming

みなさま、あるいは皆様の近くに方眼紙マスター（！？）がいらっしゃると思いますですのでご存知かとおもいますが、Excelの式は値を変更したらリアルタイムに値が書き変わります。

```
= E4 + E5
```

このセルはE4が3、E5が5ならば8になります。E5が10に書き変わったとたん、このセルは13になります。

ですが、プログラミングの世界では、この挙動は不思議です。

```coffee
a = 1
b = 2
c = a + b

#同一関数のどこか遠くは慣れた場所
a = 3
```

このとき、cの値は3です。5にはなりませんよね。

ですが、値が書き変わったとき、データの依存関係に応じて再計算を行う、これがReactiveであるということです。

この考え方に基づいたプログラミングとRactive Programmingと呼ぶ事にします。

## なんでFunctional？

ここで少し疑問が生まれます。RPはわかった、でもなんでわざわざFRPなんでしょう。
答えは簡単で、RPにおいて、副作用はいろいろ困るからです。

たとえば以下のコードを見てみましょう。

```
#Reactiveな関数??1
a = 1
b = Math.random()
c = a + b

#Reactiveな関数??2
a = 1
console.log b
b = 2
c = a + b

```

1を見てみましょう。
ここでaを書き換えたとすると、素朴に再計算してしまったら、cの値は不定です。

2はもっとたちが悪いです。
aを書き換えるたびに、bが変わっていないにも関わらず、bが出力されてしまいますね。

このように、RPにおいて副作用を持つ関数は依存関係を見た上で、特別扱いしなければならないのです。
理想を言えば、外に追い出せばいいですよね、と言う訳で、副作用と作用を厳密に切り分けられる、FPの出番になります。

##リアクティブな二つの値、Behavior、Event

余談ですが重要な概念として、この変更可能な値、二つに分類すると都合が良い事がわかってるらしいです。
それはBahaviorとEventです。

Behaviorは連続的な値です。一番わかりやすいのは時間でしょうか。
Eventは離散的な値です。例えばクリックされた、という状態を、時間とともにまとめた値等です。

#解説の準備は整った！！

というわけで解説です。遠いので一部だけ抜き出しますね。

```
form.on.register = ($)->
  unless $.checkResult
    return false
  $(disableButton)()
  processRegistration($)
  $(feedbackRegistration)()
  return true
```

form.on.registerはregisterというイベントを監視する関数の受け皿です。
これが **FRPのエントリポイントです** 。registerのイベントの値が更新されたら、直ちに実行されます。

そして、ここがポイントになってるのですが、副作用を持つ関数には、$()や、$.async()という、 **特別なマークをつけます**。
このマークが付いた場合、その関数を実行中にリアクティブな値を参照すると、依存関係があると見なします。この情報を元にすることで、副作用の値の保持、再計算を可能になります。
このマークが付いてない場合、参照透過関数であると見なし、常時再計算を行います。
値の参照に失敗した場合（例えばイベントなのに更新されていなかった場合）例外を投げて大域脱出します。そして値が更新されたら、再度実行されます。

一度実行した副作用を持つ関数は、依存する値が更新されるまで、実際には計算しません（キャッシュを参照します）。よって、次回からは参照透過です。

#あれ、どの辺がFPなの？

白状しますと、JavaScriptの記法で関数を自在に取り回すのは難しいです。
より厳密にするなら、Bacon.jsのようにならざるを得ません。

よって手続き型に見えるように書ける、そのようにしています。これが作った理由になります。

## Haskellは相変わらずすごかった

Haskellのアロー記法なるもので書いたら、こんな感じになるかもしれません。（ならないかもしれません）

```

arr checkResult >>> arr disableButton >>> arr processRegistration >>> arr feedbackRegistration

```

アロー記法は、関数をつないで大きな関数を作る物ですが、アロー記法の特異点は、そのつなぎ方によって制御構造を成す事ができると言う点です。
具体的には、以下の演算によって、制御構造を成す事が可能になります。

* A >>> B 関数をつなぐ（順次）
* A &&& B 同一入力をA、Bに流し込む（変数）
* A ||| B 右、左がわかる特別な型を受け取って、右ならB、左ならAに流し込む（条件分岐）
* 最後の口を最初にする（繰り返し）


言い換えると、 **関数を手続き的につなぐ** 手法です。
これはPure FPであるHaskellで実現できるからうまみがあるのでしょうが（命令型言語なら普通に表現できる）、考え方は同じです。

* 副作用を分離する
* 関数をつないで大きな関数を紡ぐ
* 関数の実行制御を行う

## 命令型の観点から
では、命令型の方から見てみましょうか。

疑似コードをちょっと眺めてもらえますか。

これはint main()の時代だと、わりと自然に書けるものでしたよね？
ですが、そんな素朴な時代は終わってます。猫も杓子もイベントドリブンです。

ところが、ライブラリを使って書いたFRPのコードを見てみましょう。
わざとそうしてるとはいえ、メインループでかけた、すっきりとした流れそのものじゃありませんか！！

これはいうなれば **イベントドリブンで分断された、メインループの復権** です。
難しい理論はどうでもいいんです！！これは喜ばしい事ですよ！！


#結論
関数型視点で見ると、FRPは、弱点だった離散時間を、意味を崩す事無く扱えます。
命令型視点で見ると、FRPは、ちょっとの約束事を守るだけで、メインループをこの手に取り戻せます。

FRPすごいのです！！

#で、肝心のブツは……？
https://gist.github.com/necoco/b9752cc5444ebc776c75

まだバグ残ってます（特にキャッシュ周り……）ので遊ぶ程度にしてくださいね。
書いた本人もわかりませんので解説は期待しないでください！！