start frp
TRANSCRIPT
Functional Reactive Programming はじめの一歩~ 配線プログラミング ~
@rf0444
おしながき
•スプレッドシートの話
•配線プログラミング
スプレッドシートの話
スプレッドシート?
スプレッドシート?
スプレッドシートでは当たり前の、ある機能のお話をします。
一般的なプログラム
JavaScript
一般的なプログラム
JavaScript
4 になってほしいケース
•値の変更があったら、関連する値も更新されて欲しい
•リアルタイムアプリケーション
• GUI
スプレッドシートの場合
スプレッドシートの場合
スプレッドシートの場合
スプレッドシートの場合
JavaScript での実装例 - イベント駆動
function onChange() { var a = Number($("#val1").val()); var b = Number($("#val2").val()); var c = a + b; $("#val3").text(c);}$("#val1").change(onChange);$("#val2").change(onChange);
JavaScript での実装
•イベント駆動プログラミング
•変化が起きたときに実行する「処理」を書いていく
•手続き的アプローチ
• Any other approach?
配線プログラミング
スプレッドシート と 配線 のイメージ
A1
B1
C1+
JavaScript での実装を考える
a
b
c+
Bacon.js
• JavaScript ライブラリ
•配線プログラミング をサポート
• jQuery と連携できる
•他の JavaScript フレームワークとも連携できる
• backbone.js との連携例あり
配線をつくる
a
b
c+
配線をつくる
a
b
c
配線をつくる
a
b
cBus
Bus Bus
function Model() { var me = this; me.a = new Bacon.Bus(); me.b = new Bacon.Bus(); me.c = new Bacon.Bus(); }
配線をつくる
a
b
c
function Model() { var me = this; me.a = new Bacon.Bus(); me.b = new Bacon.Bus(); me.c = new Bacon.Bus(); }
+
配線をつくる
a
b
c
function Model() { var me = this; me.a = new Bacon.Bus(); me.b = new Bacon.Bus(); me.c = new Bacon.Bus(); Bacon.combineWith(function(a, b) { return a + b; }, me.a, me.b) }
配線をつくる
+a
b
c
function Model() { var me = this; me.a = new Bacon.Bus(); me.b = new Bacon.Bus(); me.c = new Bacon.Bus(); Bacon.combineWith(function(a, b) { return a + b; }, me.a, me.b).change() }
配線をつくる
+a
b
c
function Model() { var me = this; me.a = new Bacon.Bus(); me.b = new Bacon.Bus(); me.c = new Bacon.Bus(); me.c.plug( Bacon.combineWith(function(a, b) { return a + b; }, me.a, me.b).change() );}
入力側をつなげる
+
a
b
c
入力側をつなげる
+
a
b
c
入力側をつなげる
a
入力側をつなげる
busel
function InputView(el, bus) { var me = this; me.el = el; }
a
入力側をつなげる
function InputView(el, bus) { var me = this; me.el = el; me.el.asEventStream("change") }
a
入力側をつなげる
(change event)
function InputView(el, bus) { var me = this; me.el = el; me.el.asEventStream("change") }
a
入力側をつなげる
“1”
function InputView(el, bus) { var me = this; me.el = el; me.el.asEventStream("change") .map(function() { return me.el.val(); }) }
a
入力側をつなげる
“1”初期値 ( “0” )
function InputView(el, bus) { var me = this; me.el = el; me.el.asEventStream("change") .map(function() { return me.el.val(); }) .merge(Bacon.once(me.el.val())) }
a“1” “0”
入力側をつなげる
“1”初期値 ( “0” )
function InputView(el, bus) { var me = this; me.el = el; me.el.asEventStream("change") .map(function() { return me.el.val(); }) .merge(Bacon.once(me.el.val())) .map(Number) }
a“1” “0” 1 0
入力側をつなげる
a
function InputView(el, bus) { var me = this; me.el = el; bus.plug( me.el.asEventStream("change") .map(function() { return me.el.val(); }) .merge(Bacon.once(me.el.val())) .map(Number) );}
“1”初期値 ( “0” ) 1 0“1” “0”
出力側をつなげる
+
a
b
c
出力側をつなげる
+
a
b
c
出力側をつなげる
c
function OutputView(el, bus) { var me = this; me.el = el; }
busel
出力側をつなげる
c
function OutputView(el, bus) { var me = this; me.el = el; bus.assign(function(val) { });}
val
出力側をつなげる
c
function OutputView(el, bus) { var me = this; me.el = el; bus.assign(function(val) { me.el.text(val); });}
val
完成
var model = new Model();new InputView($("#a"), model.a);new InputView($("#b"), model.b);new OutputView($("#c"), model.c);
a b c
model
+
部品プログラミング
「他の言語を学んで自由になろう」(山本和彦, http://mew.org/~kazu/material/2013-lang.pdf) より引用
部品プログラミング
「他の言語を学んで自由になろう」(山本和彦, http://mew.org/~kazu/material/2013-lang.pdf) より引用
部品プログラミング との組み合わせ
model
view1(editable)
view2
設計例
View
Model
StorageAjax
request event for model
request to server response from server
response event for model
Functional Reactive Programming (FRP)
• 下の 2 つを関数でつないでいくことで、プログラムを書いていく方法
• 時間によって変化する値 (Behavior)
• 発生するイベントの列 (Event)
• GUI だけでなく、ログなどのリアルタイム解析でも利用されている
• 「配線プログラミング」は、実は FRP のこと
利用ライブラリ
• Bacon.js
• https://github.com/raimohanska/
• Behavior → Property、Event → EventStream