リアクティブプログラミング

38
リアクティブ プログラミング 情報通信研究機構 ⾼野 祐輝

Upload: yuuki-takano

Post on 13-Apr-2017

1.171 views

Category:

Software


1 download

TRANSCRIPT

リアクティブ プログラミング

情報通信研究機構 ⾼野 祐輝

元ネタ

➤ Engineer Bainomugisha, et al.,“A Survey on Reactive Programming”, Journal of ACM Computing Surveys, Volume 45 Issue 4, August 2013, Article No. 52

2

リアクティブプログラミング

➤ イベントを扱うためのプログラミングモデル

➤ Fran(原点)

➤ Haskellのライブラリとして提供

➤ 2Dや3Dのインタラクティブなアニメーションを扱うために⽣まれた

➤ イベントのモデル化

➤ ELLIOTT, C. AND HUDAK, P. , “Functional reactive animation”, ICFP '97 Proceedings of the second ACM SIGPLAN international conference on Functional programming

3

コールバックベースなプログラミングの問題点

➤ 多くの独⽴したコード⽚が同じデータを操作する

➤ 実⾏順が予測不可能

➤ コールバック関数は返り値を持たないため、アプリケーションの状態に副作⽤を及ぼす必要がある(グローバル変数)

➤ あるAdobeのデスクトップアプリでは、バグの半分が、イベント操作のロジック部分と関連(Järvi, J. et al., “Property models: from incidental algorithms to reusable components”, ACM GPCE 2008)

➤ その他資料

➤ Edwards, J., “Coherent reaction”, ACM SIGPLAN 2009

➤ MAIER, I., ROMPF, T., AND ODERSKY, M., “Deprecating the Observer Pattern”, Tech report 2010

4

最近の流れ

➤ リアクティブプログラミングを利⽤したライブラリが登場してきた

➤ FacebookのReact.js

➤ .NETの.NET RX

➤ RxJS

➤ Frapjax

➤ RxSwift

5

リアクティブ プログラミングと

その特徴

リアクティブプログラミングにおける抽象化

➤ Behaviors

➤ 時間的に変化する値

➤ 時間経過に伴い連続的に変化する

➤ Events

➤ 時間順に並ぶ離散的な値

7t

event stream x

event stream y

behavior z = x + y1

5

6

3

2 5

4

6 11 9 5 8 9

エクセル的なモデル

Behaviorsの評価戦略

➤ 遅延評価

➤ Haskellのリアクティブプログラミング(Fran、Yampa)など

➤ 必要になった時に計算が⾏われるので無駄がない

➤ 正格評価

➤ 正格評価する⾔語も多い

➤ 無駄な計算を省くためサンプリングされる場合もある

8

Behaviorsの評価モデル、pullとpush(1)

➤ pullベース

➤ 利点

➤ 必要となる時のみ計算すれば良い

➤ Fran、YampaではHaskellの遅延評価を利⽤

➤ ⽋点

➤ イベントの配送遅延

➤ pushベースの実装

➤ Fran、NewFran、Yampa

➤ 最近のNewFranやYampaでは、遅延に関する問題は解決済みらしい

9

A Survey on Reactive Programming :5

Producer Consumer

Push data to the consumer

Pull data from the producer

The flow of data

Pull-based

Push-based

Fig. 2. Push- Versus Pull-based evaluation model

3.2. Evaluation ModelThe evaluation model of a reactive programming language is concerned with howchanges are propagated across a dependency graph of values and computations. Fromthe programmer’s point of view, propagation of changes happens automatically. Indeed,this is the essence of reactive programming. A change of a value should be automati-cally propagated to all dependent computations. When there is an event occurrence atan event source, dependent computations need to be notified about the changes, possi-bly triggering a recomputation. At the language level, the design decision that needsto be taken into account is who initiates the propagation of changes. That is, whetherthe source should “push” new data to its dependents (consumers) or the dependentsshould “pull” data from the event source (producer). In both cases the sequence of val-ues flows from the producer to the consumer as depicted in Figure 2. In the reactiveprogramming literature, there exist two evaluation models:

3.2.1. Pull-based. In the pull-based model, the computation that requires a valueneeds to “pull” it from the source. That is, propagation is driven by the demand of newdata (demand-driven). The first implementations of reactive programming languagessuch as Fran [Elliott and Hudak 1997] use the pull-based model. The pull model of-fers the flexibility that the computation requiring the value has the liberty to only pullthe new values when it actually needs it. This is thanks to the lazy evaluation of thehost language Haskell, where the actual reaction will only happen when it needs to beobserved by the outside world.

A major criticism of the pull-based model is that it may result in a significant la-tency between an event occurrence and when its reaction happens, because all delayedcomputations must suddenly be performed to lead to the reaction. This can lead tospace- and time-leaks, which may arise over time. [Hudak et al. 2003] describe space-and time-leaks as “a time-leak in a real-time system occurs whenever a time-dependentcomputation falls behind the current time because its value or effect is not needed yet,but then requires catching up at a later point in time. This catching up can take an ar-bitrarily long time (time-leak) and may or may not consume space as well (space-leak)”.This issue mainly arises in reactive languages that are implemented in a lazy lan-guage such as Fran [Elliott and Hudak 1997] and Yampa [Hudak et al. 2003]. In therecent implementation of Fran, NewFran [Elliott 2009] these issues have been fixed.Yampa [Hudak et al. 2003] avoids these problems by limiting expressiveness throughthe use of arrows [Hughes 2000] and restricting the behaviours to be non-first class.

3.2.2. Push-based. In the push-based model, when the source has new data, it pushesthe data to its dependent computations. That is, propagation is driven by availabil-ity of new data (data-driven) rather than the demand. This is the approach under-taken by all implementations of reactive programming in eager languages. This usu-

ACM Computing Surveys, Vol. , No. , Article , Publication date: 2012.

Behaviorsの評価モデル、pullとpush(2)

➤ pushベース

➤ 利点

➤ イベントの配送遅延はない

➤ ⽋点

➤ 無駄な再計算を⾏う可能性あり

➤ 例えば、GUIのウィンドウがバックグラウンドであるときは、GUIに関する計算をする必要はない。pushベースだと必ず計算する。

➤ pushベースの実装

➤ Flapjax、Scala.React、FrTime

10

A Survey on Reactive Programming :5

Producer Consumer

Push data to the consumer

Pull data from the producer

The flow of data

Pull-based

Push-based

Fig. 2. Push- Versus Pull-based evaluation model

3.2. Evaluation ModelThe evaluation model of a reactive programming language is concerned with howchanges are propagated across a dependency graph of values and computations. Fromthe programmer’s point of view, propagation of changes happens automatically. Indeed,this is the essence of reactive programming. A change of a value should be automati-cally propagated to all dependent computations. When there is an event occurrence atan event source, dependent computations need to be notified about the changes, possi-bly triggering a recomputation. At the language level, the design decision that needsto be taken into account is who initiates the propagation of changes. That is, whetherthe source should “push” new data to its dependents (consumers) or the dependentsshould “pull” data from the event source (producer). In both cases the sequence of val-ues flows from the producer to the consumer as depicted in Figure 2. In the reactiveprogramming literature, there exist two evaluation models:

3.2.1. Pull-based. In the pull-based model, the computation that requires a valueneeds to “pull” it from the source. That is, propagation is driven by the demand of newdata (demand-driven). The first implementations of reactive programming languagessuch as Fran [Elliott and Hudak 1997] use the pull-based model. The pull model of-fers the flexibility that the computation requiring the value has the liberty to only pullthe new values when it actually needs it. This is thanks to the lazy evaluation of thehost language Haskell, where the actual reaction will only happen when it needs to beobserved by the outside world.

A major criticism of the pull-based model is that it may result in a significant la-tency between an event occurrence and when its reaction happens, because all delayedcomputations must suddenly be performed to lead to the reaction. This can lead tospace- and time-leaks, which may arise over time. [Hudak et al. 2003] describe space-and time-leaks as “a time-leak in a real-time system occurs whenever a time-dependentcomputation falls behind the current time because its value or effect is not needed yet,but then requires catching up at a later point in time. This catching up can take an ar-bitrarily long time (time-leak) and may or may not consume space as well (space-leak)”.This issue mainly arises in reactive languages that are implemented in a lazy lan-guage such as Fran [Elliott and Hudak 1997] and Yampa [Hudak et al. 2003]. In therecent implementation of Fran, NewFran [Elliott 2009] these issues have been fixed.Yampa [Hudak et al. 2003] avoids these problems by limiting expressiveness throughthe use of arrows [Hughes 2000] and restricting the behaviours to be non-first class.

3.2.2. Push-based. In the push-based model, when the source has new data, it pushesthe data to its dependent computations. That is, propagation is driven by availabil-ity of new data (data-driven) rather than the demand. This is the approach under-taken by all implementations of reactive programming in eager languages. This usu-

ACM Computing Surveys, Vol. , No. , Article , Publication date: 2012.

Behaviorsの評価モデル、pullとpush(3)

➤ pull v.s. push

➤ pullの場合、behaviorsの初期値を決定しなくて良いのも利点

➤ pushだと初期値が必要

➤ (しかし、初期値を決定しないとイベントの⼊⼒待ちが発⽣するので、⼀概に利点とも⾔えないと思う)

➤ pushだとグリッチが発⽣!(後述)

➤ 両⽅使う実装もある

➤ Lula System, Fran

11

A Survey on Reactive Programming :5

Producer Consumer

Push data to the consumer

Pull data from the producer

The flow of data

Pull-based

Push-based

Fig. 2. Push- Versus Pull-based evaluation model

3.2. Evaluation ModelThe evaluation model of a reactive programming language is concerned with howchanges are propagated across a dependency graph of values and computations. Fromthe programmer’s point of view, propagation of changes happens automatically. Indeed,this is the essence of reactive programming. A change of a value should be automati-cally propagated to all dependent computations. When there is an event occurrence atan event source, dependent computations need to be notified about the changes, possi-bly triggering a recomputation. At the language level, the design decision that needsto be taken into account is who initiates the propagation of changes. That is, whetherthe source should “push” new data to its dependents (consumers) or the dependentsshould “pull” data from the event source (producer). In both cases the sequence of val-ues flows from the producer to the consumer as depicted in Figure 2. In the reactiveprogramming literature, there exist two evaluation models:

3.2.1. Pull-based. In the pull-based model, the computation that requires a valueneeds to “pull” it from the source. That is, propagation is driven by the demand of newdata (demand-driven). The first implementations of reactive programming languagessuch as Fran [Elliott and Hudak 1997] use the pull-based model. The pull model of-fers the flexibility that the computation requiring the value has the liberty to only pullthe new values when it actually needs it. This is thanks to the lazy evaluation of thehost language Haskell, where the actual reaction will only happen when it needs to beobserved by the outside world.

A major criticism of the pull-based model is that it may result in a significant la-tency between an event occurrence and when its reaction happens, because all delayedcomputations must suddenly be performed to lead to the reaction. This can lead tospace- and time-leaks, which may arise over time. [Hudak et al. 2003] describe space-and time-leaks as “a time-leak in a real-time system occurs whenever a time-dependentcomputation falls behind the current time because its value or effect is not needed yet,but then requires catching up at a later point in time. This catching up can take an ar-bitrarily long time (time-leak) and may or may not consume space as well (space-leak)”.This issue mainly arises in reactive languages that are implemented in a lazy lan-guage such as Fran [Elliott and Hudak 1997] and Yampa [Hudak et al. 2003]. In therecent implementation of Fran, NewFran [Elliott 2009] these issues have been fixed.Yampa [Hudak et al. 2003] avoids these problems by limiting expressiveness throughthe use of arrows [Hughes 2000] and restricting the behaviours to be non-first class.

3.2.2. Push-based. In the push-based model, when the source has new data, it pushesthe data to its dependent computations. That is, propagation is driven by availabil-ity of new data (data-driven) rather than the demand. This is the approach under-taken by all implementations of reactive programming in eager languages. This usu-

ACM Computing Surveys, Vol. , No. , Article , Publication date: 2012.

グリッチとその対策(1)

➤ グリッチとは

➤ パルス的に起きる電気的ノイズ

➤ 接触不良

➤ 電気素⼦の劣化などが原因

➤ Behaviorsが⼀瞬だけ間違っている場合がある

➤ COOPER, G. H. AND KRISHNAMURTHI, S. 2006. “Embedding dynamic dataflow in a call-by-value language”, In ESOPʼ06: Proceedings of the 15th European conference on Programming Languages and Systems. Springer-Verlag, Berlin, Heidelberg, 294–308.

12

-2.5 -2 -1.5 -1 -0.5 0 0.5 1 1.5 2 2.5

-1.6

-1.2

-0.8

-0.4

0.4

0.8

1.2

1.6

電気的なグリッチのイメージ

グリッチとその対策(2)

➤ グリッチの例

➤ 次のようなリアクティブプログラミングを考えてみる

➤ var1が2に変化した時なにが起きるか?

➤ 論理的には、var3はvar2の2倍(var3 = 2×var2)

➤ しかし、イベント配送のタイミング次第では、var3≠2×var2となる

13

:6 E. Bainomugisha et al.

ally involves calling a registered callback or a method [Sperber 2001a]. Most recentimplementations of reactive programming such as Flapjax [Meyerovich et al. 2009],Scala.React [Maier et al. 2010], and FrTime [Cooper and Krishnamurthi 2006] use apush-based model. Languages implementing the push-based model need an efficientsolution to the problem of wasteful recomputations since recomputations take placeevery time the input sources change. Also, because propagation of changes is data-driven, reactions happen as soon as possible [Elliott 2009].

Push Versus Pull. Each of the evaluation models has its advantages and disadvan-tages. For instance, the pull-based model works well in parts of the reactive systemwhere sampling is done on event values that change continuously over time [Sperber2001a]. Additionally, lazy languages using a pull-based approach yield an advantagewith regard to initialisation of behaviours. Since their actual values are computedlazily on a by-demand basis, initialisation does not have to happen explicitly. Espe-cially continuous behaviours will already yield a value by the time it is needed. In apush-based approach, the programmer must initialise behaviours explicitly to makesure that they hold a value when eagerly evaluating code in which they are used.

A push-based model on the other hand fits well in parts of the reactive system thatrequire instantaneous reactions. Some reactive programming languages use either apull-based or push-based model while others employ both. Another issue with push-based evaluation are glitches, which are discussed in the next section. The approachesthat combine the two models reap the benefits of the push-based model (efficiencyand low latency) and those of the pull-based model (flexibility of pulling values basedon demand). The combination of the two models has been demonstrated in the Lulasystem [Sperber 2001b] and the most recent implementation of Fran [Elliott 2009].

3.3. Glitch AvoidanceGlitch avoidance is another property that needs to be considered by a reactive lan-guage. Glitches are update inconsistencies that may occur during the propagation ofchanges. When a computation is run before all its dependent expressions are eval-uated, it may result in fresh values being combined with stale values, leading to aglitch [Cooper and Krishnamurthi 2006]. This can only happen in languages employ-ing a push-based evaluation model.

Consider an example reactive program below:

var1 = 1var2 = var1 * 1var3 = var1 + var2

In this example, the value of the variable var2 is expected to always be the sameas that of var1, and that of var3 to always be twice that of var1. Initially when thevalue of var1 is 1, the value of var2 is 1 and var3 is 2. If the value of var1 changes to,say 2, the value of var2 is expected to change to 2 while the value of var3 is expectedto be 4. However, in a naive reactive implementation, changing the value of var1 to2 may cause the expression var1 + var2 to be recomputed before the expression var1* 1. Thus the value of var3 will momentarily be 3, which is incorrect. Eventually, theexpression var1 * 1 will be recomputed to give a new value to var2 and therefore thevalue of var3 will be recomputed again to reflect the correct value 4. This behaviour isdepicted in Figure 3.

In the reactive programming literature, such a momentary view of inconsistent datais known as a glitch [Cooper and Krishnamurthi 2006]. Glitches result in incorrect pro-gram state and wasteful recomputations and therefore should be avoided by the lan-guage. Most reactive programming languages eliminate glitches by arranging expres-

ACM Computing Surveys, Vol. , No. , Article , Publication date: 2012.

グリッチとその対策(3)

14

A Survey on Reactive Programming :7

1

*

1

var11

var2

2var3

+

2

*

1

var11

var2

3var3

+

2

*

1

var12

var2

4var3

+

time

var1 = 1var2 = 1var3 = 2

var1 = 2var2 = 1var3 = 3

var1 = 2var2 = 2var3 = 4

Fig. 3. Glitches: Momentary view of inconsistent program state and recomputation.

sions in a topologically sorted graph [Cooper and Krishnamurthi 2006]; [Meyerovichet al. 2009]; [Maier et al. 2010], thus ensuring that an expression is always evaluatedafter all its dependents have been evaluated.

Most recent reactive implementations achieve glitch avoidance in reactive programsrunning on a single computer, but not in distributed reactive programs. Avoidingglitches in a distributing setting is not straightforward because of network failures,delays and lack of a global clock. This is a potential sweet spot for future researchon distributed reactive systems that provide glitch freedom. We further discuss dis-tributed reactive programming as an open issue in Section 5.

Also, an efficient reactive implementation should avoid unnecessary recomputationsof values that do not change. Dependent computations need not be recomputed if thevalue they depend on is updated to a new value that is the same as the previousvalue. Taking the same example above, suppose the value of var1 that is initially 1, isafterwards updated to the same value (i.e., 1). In such a case, the values for var2 andvar3 need not to be recomputed as the value of var1 remained unchanged.

3.4. Lifting OperationsWhen reactive programming is embedded in host languages (either as a library or as alanguage extension), existing language operators (e.g., +, *) and user defined functionsor methods must be converted to operate on behaviours. In the reactive programmingliterature the conversion of an ordinary operator to a variant that can operate on be-haviours is known as lifting.

Lifting serves a dual purpose: it transforms a function’s type signature (both thetypes of its arguments and its return type) and it registers a dependency graph in theapplication’s dataflow graph. In the following definitions, we assume functions thattake a single behaviour argument for the sake of brevity, generalising to functionsthat take multiple arguments is trivial.

lift : f(T )! flifted(Behaviour < T >)

ACM Computing Surveys, Vol. , No. , Article , Publication date: 2012.

:6 E. Bainomugisha et al.

ally involves calling a registered callback or a method [Sperber 2001a]. Most recentimplementations of reactive programming such as Flapjax [Meyerovich et al. 2009],Scala.React [Maier et al. 2010], and FrTime [Cooper and Krishnamurthi 2006] use apush-based model. Languages implementing the push-based model need an efficientsolution to the problem of wasteful recomputations since recomputations take placeevery time the input sources change. Also, because propagation of changes is data-driven, reactions happen as soon as possible [Elliott 2009].

Push Versus Pull. Each of the evaluation models has its advantages and disadvan-tages. For instance, the pull-based model works well in parts of the reactive systemwhere sampling is done on event values that change continuously over time [Sperber2001a]. Additionally, lazy languages using a pull-based approach yield an advantagewith regard to initialisation of behaviours. Since their actual values are computedlazily on a by-demand basis, initialisation does not have to happen explicitly. Espe-cially continuous behaviours will already yield a value by the time it is needed. In apush-based approach, the programmer must initialise behaviours explicitly to makesure that they hold a value when eagerly evaluating code in which they are used.

A push-based model on the other hand fits well in parts of the reactive system thatrequire instantaneous reactions. Some reactive programming languages use either apull-based or push-based model while others employ both. Another issue with push-based evaluation are glitches, which are discussed in the next section. The approachesthat combine the two models reap the benefits of the push-based model (efficiencyand low latency) and those of the pull-based model (flexibility of pulling values basedon demand). The combination of the two models has been demonstrated in the Lulasystem [Sperber 2001b] and the most recent implementation of Fran [Elliott 2009].

3.3. Glitch AvoidanceGlitch avoidance is another property that needs to be considered by a reactive lan-guage. Glitches are update inconsistencies that may occur during the propagation ofchanges. When a computation is run before all its dependent expressions are eval-uated, it may result in fresh values being combined with stale values, leading to aglitch [Cooper and Krishnamurthi 2006]. This can only happen in languages employ-ing a push-based evaluation model.

Consider an example reactive program below:

var1 = 1var2 = var1 * 1var3 = var1 + var2

In this example, the value of the variable var2 is expected to always be the sameas that of var1, and that of var3 to always be twice that of var1. Initially when thevalue of var1 is 1, the value of var2 is 1 and var3 is 2. If the value of var1 changes to,say 2, the value of var2 is expected to change to 2 while the value of var3 is expectedto be 4. However, in a naive reactive implementation, changing the value of var1 to2 may cause the expression var1 + var2 to be recomputed before the expression var1* 1. Thus the value of var3 will momentarily be 3, which is incorrect. Eventually, theexpression var1 * 1 will be recomputed to give a new value to var2 and therefore thevalue of var3 will be recomputed again to reflect the correct value 4. This behaviour isdepicted in Figure 3.

In the reactive programming literature, such a momentary view of inconsistent datais known as a glitch [Cooper and Krishnamurthi 2006]. Glitches result in incorrect pro-gram state and wasteful recomputations and therefore should be avoided by the lan-guage. Most reactive programming languages eliminate glitches by arranging expres-

ACM Computing Surveys, Vol. , No. , Article , Publication date: 2012.

最終的には正しい値に

不必要な計算&値の不整合

グリッチとその対策(4)

➤ topologically sorted graphで解決できるらしい(要調査)

➤ COOPER, G. H. AND KRISHNAMURTHI, S. 2006. “Embedding dynamic dataflow in a call-by-value language”, In ESOPʼ06: Proceedings of the 15th

European conference on Programming Languages and Systems. Springer-Verlag, Berlin, Heidelberg, 294–308.

➤ MEYEROVICH, L. A., GUHA, A., BASKIN, J., COOPER, G. H., GREENBERG, M., BROMFIELD, A., AND KRISHNAMURTHI, S. 2009. “Flapjax: a

programming language for ajax applications”, In OOPSLA ʼ09: Proceeding of the 24th ACM SIGPLAN conference on Object oriented programming

systems languages and applications. ACM, New York, NY, USA, 1–20.

➤ MAIER, I., ROMPF, T., AND ODERSKY, M. 2010. “Deprecating the Observer Pattern”,Tech. rep.

➤ 分散リアクティブプログラミングでは未解決の問題

➤ ネットワーク障害

➤ 遅延、パケロス

➤ グローバルクロックが無い

➤ 今後の研究課題

15

リフティングとその戦略(1)

➤ 既存のホスト⾔語にリアクティブプログラミングが導⼊された場合に、リフティングと呼ばれる操作が必要となる

➤ リフティングで何をするか?

➤ +、ー、*、/などのプリミティブな演算に対するリアクティブプログラミング対応

➤ 関数呼び出しに対するリアクティブプログラミング対応

16

リフティングとその戦略(2)

➤ リフティングの定義

➤ あるタイムステップ i においては、リアクティブでない普通の関数と等価

17

A Survey on Reactive Programming :7

1

*

1

var11

var2

2var3

+

2

*

1

var11

var2

3var3

+

2

*

1

var12

var2

4var3

+

time

var1 = 1var2 = 1var3 = 2

var1 = 2var2 = 1var3 = 3

var1 = 2var2 = 2var3 = 4

Fig. 3. Glitches: Momentary view of inconsistent program state and recomputation.

sions in a topologically sorted graph [Cooper and Krishnamurthi 2006]; [Meyerovichet al. 2009]; [Maier et al. 2010], thus ensuring that an expression is always evaluatedafter all its dependents have been evaluated.

Most recent reactive implementations achieve glitch avoidance in reactive programsrunning on a single computer, but not in distributed reactive programs. Avoidingglitches in a distributing setting is not straightforward because of network failures,delays and lack of a global clock. This is a potential sweet spot for future researchon distributed reactive systems that provide glitch freedom. We further discuss dis-tributed reactive programming as an open issue in Section 5.

Also, an efficient reactive implementation should avoid unnecessary recomputationsof values that do not change. Dependent computations need not be recomputed if thevalue they depend on is updated to a new value that is the same as the previousvalue. Taking the same example above, suppose the value of var1 that is initially 1, isafterwards updated to the same value (i.e., 1). In such a case, the values for var2 andvar3 need not to be recomputed as the value of var1 remained unchanged.

3.4. Lifting OperationsWhen reactive programming is embedded in host languages (either as a library or as alanguage extension), existing language operators (e.g., +, *) and user defined functionsor methods must be converted to operate on behaviours. In the reactive programmingliterature the conversion of an ordinary operator to a variant that can operate on be-haviours is known as lifting.

Lifting serves a dual purpose: it transforms a function’s type signature (both thetypes of its arguments and its return type) and it registers a dependency graph in theapplication’s dataflow graph. In the following definitions, we assume functions thattake a single behaviour argument for the sake of brevity, generalising to functionsthat take multiple arguments is trivial.

lift : f(T )! flifted(Behaviour < T >)

ACM Computing Surveys, Vol. , No. , Article , Publication date: 2012.

リアクティブな値を 扱えない従来の関数を

リアクティブな値を取る関数に変換

:8 E. Bainomugisha et al.

In this definition, T is a non-behaviour type while Behaviour is a behaviour typeholding values of type T . Therefore, lifting an operator f that was defined to operateon a non-behaviour value transforms it into a lifted version flifted that can be appliedon a behaviour.

At time step i, evaluation of a lifted function f called with a behaviour yielding valuesof type T can be defined as follows:

flifted(Behaviour < T >)! f(Ti)

Here, Ti denotes the value of Behaviour at time step i.3.4.1. Relation Between Typing and Lifting. In the body of work discussed in this survey,

lifting happens in a number of different ways. Before discussing them, it is importantto understand the interplay between the semantics of the host language and trans-forming a function’s type signature. In a statically typed language (such as Haskellor Java), a function or method cannot be directly applied onto a behaviour. Usually,this means that the programmer must explicitly lift procedures or methods to ensuretype safety (or write functions or methods that expect behaviour arguments, i.e., theirparameters are statically typed Behaviour). The need for explicit lifting is mitigatedin many of the statically typed languages discussed in this survey because these lan-guages offer a rich set of overloaded primitives intended for their particular problemdomain that work on behaviours as well. Of course, this is only true when the languageis restricted to the domain for which adequate overloaded operators are provided bythe language.

In dynamically typed languages, one can pass behaviours as arguments to functionswithout having to explicitly lift them to satisfy the type system. In these languages,lifting usually happens implicitly by the language. Of course, at one moment primi-tive operators of the language will have to be applied to arguments of an unexpectedtype Behaviour (e.g., computing the sum of two behaviours). In dynamically typed lan-guages, these primitive operators must be properly overloaded to their lifted version(by, for example, using code transformation techniques to generate lifted operators) bythe language.

3.4.2. Classification of Lifting Strategies. In this section, we classify the different ways inwhich the languages that are surveyed in this paper support lifting.

Implicit lifting. In the implicit lifting approach, when an ordinary language operatoris applied on a behaviour, it is automatically “lifted”. Implicit lifting makes reactiveprogramming transparent, since programmers can freely use existing operators onbehaviours.

f(b1)! flifted(b1)

In this definition, when an ordinary operator f is applied on a behaviour b1, it is implic-itly lifted to flifted. This is the approach undertaken by dynamically typed languages.

Explicit lifting. With explicit lifting, the language provides a set of combinators thatcan be used to “lift” ordinary operators to operate on behaviours.

lift(f)(b1)! flifted(b1)

In this definition, the ordinary operator f is explicitly lifted using the combinator lift

to be able to operate on the behaviour b1. This is the approach that is usually under-taken by statically typed languages. In many cases, reactive programming systems

ACM Computing Surveys, Vol. , No. , Article , Publication date: 2012.

ここで Ti はタイムステップ i におけるBehaviorの値

リフティングとその戦略(3)

➤ 静的型付け⾔語に対する適⽤

➤ 静的型付けなので、関数を直接変換することは出来ない

➤ プログラマがリフト操作を⾏う必要がある

➤ ⼀般的には⾔語の提供するオーバーロードの機能を⽤いて、なるべく簡単に出来るような⼯夫がされている

➤ 動的型付け⾔語に対する適⽤

➤ 関数については、Behaviorsも普通に引数として受け取れる

➤ ⾔語内部で暗黙的に処理される

➤ プリミティブな演算については、演算⼦オーバーロードや、コード⽣成時に⼯夫が必要

18

リフティングとその戦略(4)

➤ 暗黙的リフティング

➤ 動的型付け⾔語で⽤いられる⼿法

➤ 明⽰的リフティング

➤ 静的型付け⾔語で⽤いられる⼿法

➤ オーバーロードなどで対応している場合もこちらに分類

➤ ⼿動リフティング

➤ ⾔語レベルでのサポート無しの場合は、⼿動で現在のBehaviorsの値をわたす必要がある

19

:8 E. Bainomugisha et al.

In this definition, T is a non-behaviour type while Behaviour is a behaviour typeholding values of type T . Therefore, lifting an operator f that was defined to operateon a non-behaviour value transforms it into a lifted version flifted that can be appliedon a behaviour.

At time step i, evaluation of a lifted function f called with a behaviour yielding valuesof type T can be defined as follows:

flifted(Behaviour < T >)! f(Ti)

Here, Ti denotes the value of Behaviour at time step i.3.4.1. Relation Between Typing and Lifting. In the body of work discussed in this survey,

lifting happens in a number of different ways. Before discussing them, it is importantto understand the interplay between the semantics of the host language and trans-forming a function’s type signature. In a statically typed language (such as Haskellor Java), a function or method cannot be directly applied onto a behaviour. Usually,this means that the programmer must explicitly lift procedures or methods to ensuretype safety (or write functions or methods that expect behaviour arguments, i.e., theirparameters are statically typed Behaviour). The need for explicit lifting is mitigatedin many of the statically typed languages discussed in this survey because these lan-guages offer a rich set of overloaded primitives intended for their particular problemdomain that work on behaviours as well. Of course, this is only true when the languageis restricted to the domain for which adequate overloaded operators are provided bythe language.

In dynamically typed languages, one can pass behaviours as arguments to functionswithout having to explicitly lift them to satisfy the type system. In these languages,lifting usually happens implicitly by the language. Of course, at one moment primi-tive operators of the language will have to be applied to arguments of an unexpectedtype Behaviour (e.g., computing the sum of two behaviours). In dynamically typed lan-guages, these primitive operators must be properly overloaded to their lifted version(by, for example, using code transformation techniques to generate lifted operators) bythe language.

3.4.2. Classification of Lifting Strategies. In this section, we classify the different ways inwhich the languages that are surveyed in this paper support lifting.

Implicit lifting. In the implicit lifting approach, when an ordinary language operatoris applied on a behaviour, it is automatically “lifted”. Implicit lifting makes reactiveprogramming transparent, since programmers can freely use existing operators onbehaviours.

f(b1)! flifted(b1)

In this definition, when an ordinary operator f is applied on a behaviour b1, it is implic-itly lifted to flifted. This is the approach undertaken by dynamically typed languages.

Explicit lifting. With explicit lifting, the language provides a set of combinators thatcan be used to “lift” ordinary operators to operate on behaviours.

lift(f)(b1)! flifted(b1)

In this definition, the ordinary operator f is explicitly lifted using the combinator lift

to be able to operate on the behaviour b1. This is the approach that is usually under-taken by statically typed languages. In many cases, reactive programming systems

ACM Computing Surveys, Vol. , No. , Article , Publication date: 2012.

:8 E. Bainomugisha et al.

In this definition, T is a non-behaviour type while Behaviour is a behaviour typeholding values of type T . Therefore, lifting an operator f that was defined to operateon a non-behaviour value transforms it into a lifted version flifted that can be appliedon a behaviour.

At time step i, evaluation of a lifted function f called with a behaviour yielding valuesof type T can be defined as follows:

flifted(Behaviour < T >)! f(Ti)

Here, Ti denotes the value of Behaviour at time step i.3.4.1. Relation Between Typing and Lifting. In the body of work discussed in this survey,

lifting happens in a number of different ways. Before discussing them, it is importantto understand the interplay between the semantics of the host language and trans-forming a function’s type signature. In a statically typed language (such as Haskellor Java), a function or method cannot be directly applied onto a behaviour. Usually,this means that the programmer must explicitly lift procedures or methods to ensuretype safety (or write functions or methods that expect behaviour arguments, i.e., theirparameters are statically typed Behaviour). The need for explicit lifting is mitigatedin many of the statically typed languages discussed in this survey because these lan-guages offer a rich set of overloaded primitives intended for their particular problemdomain that work on behaviours as well. Of course, this is only true when the languageis restricted to the domain for which adequate overloaded operators are provided bythe language.

In dynamically typed languages, one can pass behaviours as arguments to functionswithout having to explicitly lift them to satisfy the type system. In these languages,lifting usually happens implicitly by the language. Of course, at one moment primi-tive operators of the language will have to be applied to arguments of an unexpectedtype Behaviour (e.g., computing the sum of two behaviours). In dynamically typed lan-guages, these primitive operators must be properly overloaded to their lifted version(by, for example, using code transformation techniques to generate lifted operators) bythe language.

3.4.2. Classification of Lifting Strategies. In this section, we classify the different ways inwhich the languages that are surveyed in this paper support lifting.

Implicit lifting. In the implicit lifting approach, when an ordinary language operatoris applied on a behaviour, it is automatically “lifted”. Implicit lifting makes reactiveprogramming transparent, since programmers can freely use existing operators onbehaviours.

f(b1)! flifted(b1)

In this definition, when an ordinary operator f is applied on a behaviour b1, it is implic-itly lifted to flifted. This is the approach undertaken by dynamically typed languages.

Explicit lifting. With explicit lifting, the language provides a set of combinators thatcan be used to “lift” ordinary operators to operate on behaviours.

lift(f)(b1)! flifted(b1)

In this definition, the ordinary operator f is explicitly lifted using the combinator lift

to be able to operate on the behaviour b1. This is the approach that is usually under-taken by statically typed languages. In many cases, reactive programming systems

ACM Computing Surveys, Vol. , No. , Article , Publication date: 2012.

A Survey on Reactive Programming :9

target a particular problem domain, for which it offers a rich set of overloaded primi-tives that directly work on behaviours. In this survey, we still classify this as explicitlifting, but we mention in the discussion of the language in question when primitiveoperators are overloaded to deal with behaviours.

Manual Lifting. With manual lifting, the language does not provide lifting operators.Instead, the programmer needs to manually obtain the current value of a time-varyingvalue, which can then be used with ordinary language operators.

f(b1)! f(currentvalue(b1))

In this definition, the current value of the time-varying value b1 is obtained that is thenused for the ordinary operator f . In languages that do not offer first-class behaviours,lifting must always happen manually by manually putting values in wrapper values(sometimes called cells) that encode their dataflow dependencies.

Table I shows how reactive languages compare in terms of lifting operations.

3.5. MultidirectionalityAnother property of reactive programming languages is whether propagation ofchanges happens in one direction (unidirectional) or in either direction (multidirec-tional). With multidirectionality, changes in derived values are propagated back to thevalues from which they were derived. For example, writing an expression F = (C *1.8) + 32 for converting temperature between Fahrenheit and Celsius, implies thatwhenever a new value of either F or C is available the other value is updated. Thisproperty is similar to the multidirectional constraints in the constraint programmingparadigm [Steele 1980]. Table I shows the surveyed reactive languages that providesupport for multidirectionality.

3.6. Support for DistributionThis property is concerned with whether a reactive language provides support for writ-ing distributed reactive programs. The support for distribution enables one to cre-ate dependencies between computations or data that are distributed across multiplenodes. For example, in an expression var3 = var1 + var2, var1, var2 and var3 can belocated on different nodes. The need for support for distribution in a reactive languageis motivated by the fact that interactive applications (e.g., Web applications, mobileapplications, etc.) are becoming increasingly distributed. However, there is a catch inadding support for distribution to a reactive language. It is more difficult to ensureconsistency in a dependency graph that is distributed across multiple nodes because ofdistributed programming characteristics (such as latency, network failures, etc.). Wefurther discuss this challenge as of one of the open issues in Section 5. In the Table I,the column for distribution shows how different reactive languages compare in termsof support for distribution.

3.7. DiscussionTable I presents a taxonomy of the reactive programming languages that we discussin this paper. We evaluate the languages along the aforementioned six axes: basic ab-stractions, evaluation model, lifting, multidirectionality, glitch avoidance, and supportfor distribution. Y in the table under the property column signifies that a languageprovides the feature while N signifies that a language does not provide that feature.

3.7.1. Basic abstractions. Most reactive languages provide the same basic composableabstractions, behaviours and events, for representing continuous values and discretevalues. In this survey, we consider those languages to be siblings, as they inherit theirdistinctive features from a single progenitor: Fran [Elliott and Hudak 1997]. There are

ACM Computing Surveys, Vol. , No. , Article , Publication date: 2012.

多⽅向性

➤ イベントの伝達⽅向が、⼀⽅向か双⽅向か

➤ 例:摂⽒華⽒変換

➤ F = C * 1.8 + 32

➤ Cが変化するとFの値が変化(ここまで⼀⽅向)

➤ 上の等式は次のように変換できる

➤ C = (F ー 32) / 1.8

➤ Fが変化するとCも変化すると双⽅向

➤ 制約プログラミングと似ている20

分散リアクティブプログラミング

➤ 分散環境でのリアクティブプログラミングは達成できるか?

➤ 問題点

➤ ⼀貫性の保証ができるのか?

➤ グリッチの解決が更に難しく

➤ グローバルクロック無し

➤ パケットロス

➤ レイテンシ

21

リアクティブ プログラミングの種類

:10

E.B

aino

mug

isha

etal

.

Table I. A taxonomy of reactive programming languagesLanguage Basic abstractions Evaluation

modelLifting Multidirectionality Glitch

avoidanceSupport fordistribution

FRP Siblings

Fran behaviours and events Pull Explicit N Y NYampa signal functions and

eventsPull Explicit N Y N

FrTime behaviours and events Push Implicit N Y NNewFran behaviours and events Push and

PullExplicit N Y N

Frappe behaviours and events Push Explicit N N NScala.React signals and events Push Manual N Y NFlapjax behaviours and events Push Explicit and

implicitN Y (local) Y

AmbientTalk/R behaviours and events Push Implicit N Y (local) Y

Cousins of Reactive Programming

Cells rules, cells and ob-servers

Push Manual N Y N

Lamport Cells reactors and reporters Push andPull

Manual N N Y

SuperGlue signals, components,and rules

Push Manual N Y N

Trellis cells and rules Push Manual N Y* NRadul/SussmanPropagators

propagators and cells Push Manual Y N N

Coherence reactions and actions Pull N/A Y Y N.NET Rx events Push Manual N N? N

AC

MC

ompu

ting

Surv

eys,

Vol.

,No.

,Art

icle

,Pub

licat

ion

date

:20

12.

リアクティブプログラミングの分類

24

:12 E. Bainomugisha et al.

Programming languages for expressing reactive systems

Synchronous, dataflow and synchronous dataflow languages

The cousins of reactive proramming

The FRP siblings

Fig. 4. Classification of languages for reactive programming.

pen in one direction. We further discuss the support for multidirectionality in reactiveprogramming languages as an open issue in Section 5.

3.7.5. Glitch avoidance. Most of the surveyed reactive languages achieve glitch free-dom. However, there are a few exceptions. Radul/Sussman Propagators are not imple-mented with support for glitch avoidance. Programmers need to employ other tech-niques such as dependency-directed tracking [Stallman and Sussman 1977]; [Zabihet al. 1987] that can be easily expressed in the base propagator infrastructure. Trel-lis has some support for glitch avoidance, however programmers have to take extracare on program structuring in order to realise glitch freedom (thus indicated as Y*)..NET Rx is an ongoing project and there is no clear description of the semantics of howglitches are avoided (thus indicated as N? in the table).

3.7.6. Support for distribution. Distribution is a feature that is not well supported in thereactive programming languages. We found only three languages: Flapjax [Meyerovichet al. 2009], Lamport Cells [Miller 2003], and AmbientTalk/R [Carreton et al. 2010],that provide support for writing distributed reactive programs. However, even in theselanguages glitches are avoided only in a local setting (thus indicated Y(local)). Thisobservation shows that there is still need for research in the field of distributed reac-tive programming.

In Section 4 we give a full review for each language listed in Table I.

4. LANGUAGE SURVEYOur survey consists of 15 representative reactive programming languages that we se-lected based on the availability of their publications. Most of the reactive languagessurveyed are built as language extensions to existing languages. Several reactive lan-guages are extensions to (mostly) functional programming languages such as Haskelland Scheme.

For this survey we sort the reactive languages into three categories: The functionalreactive programming (FRP) siblings, the cousins of reactive programming, and syn-chronous, dataflow and synchronous dataflow languages. The classification is depictedin Figure 4. We discuss each language based on the features outlined in Section 3. Weillustrate each language with a simple temperature converter example. Where neces-sary we further illustrate the language with an example of drawing a circle on thescreen that changes colour when the left or right mouse button is pressed.

4.1. The FRP SiblingsThe reactive programming languages in this category provide composable abstractions(behaviours and events). In addition, they typically provide primitive combinators for

ACM Computing Surveys, Vol. , No. , Article , Publication date: 2012.

関数型リアクティブプログラミング(FRP)

➤ 関数の引数がイベント

➤ 引数の値が変わる(イベントが発⽣する)と⾃動的に関数が呼ばれる

➤ 例:

➤ (draw-circle mouse-x mouse-y)

➤ mouse-x、mouse-yの値が変わるとdraw-circle関数が⾃動的に呼ばれる

➤ 関数型⾔語と関数型リアクティブプログラミングは直接関係ない

➤ 関数でリアクティブプログラミングを実現するのがFRP

➤ 関数型⾔語でなくてもFRPは実現可能25

関数型リアクティブプログラミングの種類

26

A Survey on Reactive Programming :13

Table II. Functional reactive programming (FRP) siblingsLanguage Host languageFran [Elliott and Hudak 1997] HaskellYampa [Hudak et al. 2003] HaskellFrappe [Courtney 2001] JavaFrTime [Cooper and Krishnamurthi 2006] PLT Scheme (now

known as Racket)NewFran [Elliott 2009] HaskellFlapjax [Meyerovich et al. 2009] JavaScriptScala.React [Maier et al. 2010] ScalaAmbientTalk/R [Carreton et al. 2010] AmbientTalk

composing events and switching combinators to support the dynamic reconfigurationof the dataflow and support higher-order dataflow.

One important point is that the literature on these languages sometimes usesslightly different terminology for behaviours and events, while sometimes the abstrac-tions truly differ. In the following, we will always relate the offered abstractions to ourterminology of behaviours and events and stick to this where possible.

In FRP languages, the arguments to functions vary over time and automaticallytrigger propagation whenever values change. That is, the function is automatically re-applied as soon as one of the arguments changes. FRP allows programmers to expressreactive programs in a declarative style. For instance, a sample functional program todraw a circle on the screen at the current mouse position can be easily expressed as(draw-circle mouse-x mouse-y). In this expression, whenever the value of mouse-x ormouse-y changes, the function draw-circle is automatically re-applied to update thecircle position. Elliot et.al [Elliott and Hudak 1997] identify the key advantages of theFRP paradigm as: clarity, ease of construction, composability, and clean semantics.

FRP was introduced in Fran [Elliott and Hudak 1997], a language specially designedfor developing interactive graphics and animations in Haskell. Since then, FRP ideashave been explored in different languages including Yampa, FrTime, Flapjax, etc. In-novative research on reactive programming has been mostly carried out in the contextof FRP. It is therefore not surprising that a large number of the surveyed languagesevolve around the notion of FRP. We review 8 languages (outlined in Table II) in thiscategory.

FranFran (Functional Reactive Animation) [Elliott and Hudak 1997] is one of the first lan-guages designed to ease the construction of interactive multimedia animations. Franwas conceived as a reactive programming library embedded in Haskell. Its main goal isto enable programming interactive animations with high-level abstractions that pro-vide ways of expressing what the application does and let the language take care ofhow the interaction occurs.

Fran represents continuous time-varying values as behaviours while discrete valuesare represented as events. Both behaviours and events are first-class values and can becomposed using combinators. Behaviours are expressed as reactions to events or otherbehaviours. In other words, behaviours are built up from events and other behavioursusing combinators.

As Haskell is a statically typed host language, Fran provides lifting operators thattransform ordinary Haskell functions into behaviours. Hence, lifting must happen ex-plicitly using these operators. In addition, Fran offers a rich set of overloaded primitiveoperators that are lifted to work on behaviours as well. Many of these primitives are

ACM Computing Surveys, Vol. , No. , Article , Publication date: 2012.

関数型でないリアクティブプログラミングの種類

27

A Survey on Reactive Programming :23

Table III. The cousins of reactive programmingLanguage Host languageCells [Tilton 2008] CLOSLamport Cells [Miller 2003] ESuperGlue [McDirmid and Hsieh 2006] JavaTrellis [Eby 2008] PythonRadul/Sussman Propagators [Radul and Sussman 2009] MIT/GNU SchemeCoherence [Edwards 2009] Coherence.NET Rx [Hamilton and Dyer 2010] C#.NET

4.2. The Cousins of Reactive ProgrammingAs discussed in Section 3.7, there are a few reactive languages that do not provideprimitive abstractions for representation of time-varying values and primitive switch-ing combinators for dynamic reconfiguration but provide support for automatic prop-agation of state changes and other features of reactive programming such as glitchavoidance. Since their abstractions for representing time-varying values do not inte-grate with the rest of the language, lifting must always performed manually by theprogrammer in these languages. We refer to those languages as cousins of reactiveprogramming. Table III outlines the reactive languages in this category.

As with the FRP siblings, we illustrate each cousin reactive language with the tem-perature conversion example. However, since these languages do not provide eventand behaviour combinators such as merge, map-e, and switch, it is difficult to expresssome applications such as that of drawing a circle that starts with a colour red andswitches to green or red depending on the left or right mouse button is pressed.

CellsCells [Tilton 2008] is a reactive programming extension to the Common Lisp ObjectSystem (CLOS). It allows programmers to define classes whose instances can haveslots that trigger events when their values change. These slots are known as cells.Such classes are defined using the defmodel abstraction, which is similar to defclassfor class definition in CLOS, but with support for defining cells as slots.

A programmer can define dependencies between cells such that when a value ofone cell changes, all the dependent cells are updated. In addition, cells can get theirvalues by evaluating rules that are specified at instance creation time. Rules containregular CLOS code as well as reads of other cells. Rules are run immediately afterinstantiation and any reads to other cell slots create dependencies between the cell onwhich the rule is specified and the cell being read.

Computations external to the object model need to be defined as observer functions.One can define an observer function that is invoked when a cell of a specified nameis updated to a new value. Any observer function is guaranteed to be invoked at leastonce during the instance creation process.

The propagation of changes in Cells is push-based. That is, when a cell slot is as-signed a new value, all dependent cells rules are rerun and observers are notified toreflect the changes. The Cells engine ensures that values that do not change are notpropagated, thereby avoiding wasteful recomputations. It also avoids glitches by ensur-ing that all dependent cells and observers see only up-to-date values. The temperatureconversion example can be expressed as follows in Cells.

ACM Computing Surveys, Vol. , No. , Article , Publication date: 2012.

リアクティブ プログラミングの実例

Fran

➤ 1997年に考案された、⼀番初めのリアクティブプログラミング⾔語

➤ ホスト⾔語はHaskell

➤ 関数型リアクティブプログラミング

➤ リフティングは明⽰的に⾏う

➤ ただし、多くの場合でオーバーロードで対応可能

➤ 当初はpullベースでの実装だった

➤ あとでpushにも対応

➤ ELLIOTT, C. M. 2009. “Push-pull functional reactive programming”, In Proceedings of the 2nd ACM

SIGPLAN symposium on Haskell. Haskell ʼ09. ACM, New York, NY, USA, 25–36.

29

Franの例(1)

➤ 摂⽒華⽒変換

➤ tempは定義済みのbehavior

30

:14 E. Bainomugisha et al.

specifically targeted to its problem domain: animation. In many cases, they eliminatethe need to explicitly lift operators for this particular problem domain.

The first implementation of Fran employs a purely pull-based evaluation model.However, the recent implementation of Fran [Elliott 2009] (that we refer to asNewFran in this paper), combines push- and pull-based evaluation models. The com-bination of these models yields the benefit of values being recomputed only when theyare necessary, and almost instantaneous reactions. The temperature conversion exam-ple can be realised in Fran as follows.

tempConverter :: Behavior DoubletempConverter = tempF

wheretempC = temptempF = (tempC*1.8)+32

tempConverter is a function that returns a behaviour whose value at any given pointin time is the value of the current temperature in degrees Fahrenheit. We assume thatthere is a predefined behaviour temp whose value at any given time is the currenttemperature in degrees Celsius.

In order to illustrate Fran’s support for the dynamic dataflow structure and high-order reactivity, we consider an example of drawing a circle on the screen and paintingit red. The colour of the circle then changes to either green when the left mouse buttonis pressed or red when the right mouse button is pressed. This example also appearsin [Elliott and Hudak 1997]. Such a program in Fran can be easily expressed as follows:

drawcircle :: ImageBdrawcircle = withColour colour circle

wherecolour = stepper red (lbp -=> green .|. rbp -=> red)

In the above example, circle is a predefined behaviour for a circle while lbp and rbpare events that represent left button presses and right button presses respectively. Themerge operator .|. produces events when either input events have an occurrence. Weuse the stepper combinator to create the colour behaviour that starts with red untilthe first button press at which point it changes to either green or red. withColour isa predefined function that takes as argument the colour behaviour and paints thecircle with the colour. Since colour is a behaviour, the function withColour will beautomatically reapplied when the colour behaviour gets a new value.

YampaDeveloped at Yale University, Yampa [Hudak et al. 2003] is a functional reactive lan-guage that is based on Fran. Like Fran, Yampa is embedded in Haskell. It is speciallydesigned for programming reactive systems where performance is critical. In Yampa,a reactive program is expressed using arrows, (a generalisation of monads) [Hughes2000] which reduce the chance of introducing the problems of space- and time-leaks.

The basic reactive abstractions in Yampa are signal functions and events. Signalfunctions differ from behaviours in the sense that they are functions that encapsu-late time-varying values, but are similar in the sense that they are first-class. Eventsin Yampa are represented as signal functions that represent an event stream (eventsource) that yields an event carrying a certain value at any point in time. Yampa pro-vides primitive combinators for composing events (e.g., merging events). Additionally,it provides a set of switching combinators to provide support for the dynamic dataflowstructure. Its parallel switching combinators allow the support for dynamic collections

ACM Computing Surveys, Vol. , No. , Article , Publication date: 2012.

tempの値が変わるとtempConverterの値も⾃動的に変わる

Franの例(2)

➤ 円を書く関数

➤ lbp、rbpはevent

➤ withColorは描画関数

➤ circleは事前に定義されたbehavior

31

:14 E. Bainomugisha et al.

specifically targeted to its problem domain: animation. In many cases, they eliminatethe need to explicitly lift operators for this particular problem domain.

The first implementation of Fran employs a purely pull-based evaluation model.However, the recent implementation of Fran [Elliott 2009] (that we refer to asNewFran in this paper), combines push- and pull-based evaluation models. The com-bination of these models yields the benefit of values being recomputed only when theyare necessary, and almost instantaneous reactions. The temperature conversion exam-ple can be realised in Fran as follows.

tempConverter :: Behavior DoubletempConverter = tempF

wheretempC = temptempF = (tempC*1.8)+32

tempConverter is a function that returns a behaviour whose value at any given pointin time is the value of the current temperature in degrees Fahrenheit. We assume thatthere is a predefined behaviour temp whose value at any given time is the currenttemperature in degrees Celsius.

In order to illustrate Fran’s support for the dynamic dataflow structure and high-order reactivity, we consider an example of drawing a circle on the screen and paintingit red. The colour of the circle then changes to either green when the left mouse buttonis pressed or red when the right mouse button is pressed. This example also appearsin [Elliott and Hudak 1997]. Such a program in Fran can be easily expressed as follows:

drawcircle :: ImageBdrawcircle = withColour colour circle

wherecolour = stepper red (lbp -=> green .|. rbp -=> red)

In the above example, circle is a predefined behaviour for a circle while lbp and rbpare events that represent left button presses and right button presses respectively. Themerge operator .|. produces events when either input events have an occurrence. Weuse the stepper combinator to create the colour behaviour that starts with red untilthe first button press at which point it changes to either green or red. withColour isa predefined function that takes as argument the colour behaviour and paints thecircle with the colour. Since colour is a behaviour, the function withColour will beautomatically reapplied when the colour behaviour gets a new value.

YampaDeveloped at Yale University, Yampa [Hudak et al. 2003] is a functional reactive lan-guage that is based on Fran. Like Fran, Yampa is embedded in Haskell. It is speciallydesigned for programming reactive systems where performance is critical. In Yampa,a reactive program is expressed using arrows, (a generalisation of monads) [Hughes2000] which reduce the chance of introducing the problems of space- and time-leaks.

The basic reactive abstractions in Yampa are signal functions and events. Signalfunctions differ from behaviours in the sense that they are functions that encapsu-late time-varying values, but are similar in the sense that they are first-class. Eventsin Yampa are represented as signal functions that represent an event stream (eventsource) that yields an event carrying a certain value at any point in time. Yampa pro-vides primitive combinators for composing events (e.g., merging events). Additionally,it provides a set of switching combinators to provide support for the dynamic dataflowstructure. Its parallel switching combinators allow the support for dynamic collections

ACM Computing Surveys, Vol. , No. , Article , Publication date: 2012.

左ボタンクリックなら緑に 右ボタンクリックなら⾚に初期値

Flapjaxの例(1)

➤ JavaScript上でFRPを実現

➤ pushベース

➤ 関数型リアクティブプログラミング

32

:18 E. Bainomugisha et al.

function tempConverter() {var temp = Temperature();var tempC = temp;var tempF = tempC * 1.8 + 32;insertValueB(tempC, "tempCtext", "innerHTML");insertValueB(tempF, "tempFtext", "innerHTML");

}

<body onLoad = "tempConverter()"><div id= "tempCtext"> </div><div id= "tempFtext"> </div></body>

The tempConverter function implements the functionality of converting temperaturefrom degrees Celsius to degrees Fahrenheit. We assume that there is a predefinedbehaviour Temperature whose value at any given point in time is the current tempera-ture. The insertValueB function inserts the values of the behaviours tempC and tempFin the DOM elements.

We further illustrate Flapjax’s support for first-class behaviours and primitive com-binators using the example of drawing on a circle a screen that changes colour depend-ing on whether a left or right mouse button is pressed. The example can be expressedas follows.

//draw circle at (x,y) and paint it colourfunction drawcircle(x, y, colour) {...};

//map button press to colourfunction handleMouseEvent(evt) {...};

var buttonE = extractEventE(document,"mousedown");var colourE = buttonE.mapE(handleMouseEvent);var colourB = startsWith(colourE, "red");var canvas = document.getElementById(’draw’);drawcircle(mouseLeftB(canvas), mouseTopB(canvas), colourB);

In the above example, we use Flapjax’s combinators extractEventE and mapE to ex-tract mousedown events from the DOM and transform them into colour events. Thefunction handleMouseEvent defines the logic of transforming button presses to colour.The startsWith combinator is similar to the stepper in Fran. It takes as argumentsthe colour event colourE and initial value "red" creates a behaviour with the initialvalue as the red colour and changes value to green or red whenever a mouse buttonpress event occurs. The drawcircle function takes as argument the mouse positionand colour behaviours and draws the circle on the screen when the mouse positionor colour changes. mouseLeftB and mouseTopB are Flapjax’s combinators that create abehaviour carrying the x- or y-coordinate of the mouse, relative to the specified DOMelement.

FrappeFrappe [Courtney 2001] is a functional reactive programming library for Java. It ex-tends the JavaBeans component model [Oracle 1997] with a set of classes that corre-spond to functional reactive programming combinators. In Frappe, a reactive programis constructed by instantiating JavaBeans classes and connecting the components us-ing the FRP combinators. Frappe defines two Java interfaces, FRPEventSource and

ACM Computing Surveys, Vol. , No. , Article , Publication date: 2012.

behaviors

events

lifting

どういう仕組かわからないけれど、colourBが変更されたり、

リドローするときに、drawcircleが呼び出される。すごい。

Flapjaxの例(2)

➤ http://www.flapjax-lang.org/try/index.html?edit=mouse_coords.fx

➤ マウスを動かすとHTMLが勝⼿に更新される謎技術

33

<html> <head> <title>Flapjax Demo: Where is the Mouse?</title> <link rel="stylesheet" href="/demo.css"/> </head> <body>

<p>The mouse coordinates are &lt; {! mouseLeftB(document) !}, {! mouseTopB(document) !} &gt; </p>

</body> </html>

Trellisの例

➤ Python上で構築された、リアクティブプログラミング環境

➤ glich回避は部分的にされているが、完全ではないらしい?(詳細は調べていない)

➤ push型のモデル

➤ 関数型じゃないリアクティブプログラミング

34

:26 E. Bainomugisha et al.

class TempConverter(trellis.Component):tempC = trellis.attr(Temperature)tempF = trellis.maintain(

lambda self: self.tempC * 1.8 + 32,initially = 32

)

@trellis.performdef viewGUI(self):

display "Celsius: ", self.tempCdisplay "Fahrenheit: ", self.tempF

The above code snippet defines the TempConverter class that is derived fromtrellis.Component. A trellis.Component is an object whose attributes are reactive.The attr form creates an attribute that is writable. In this example we assume thatthere is a predefined variable Temperature whose value is used to initialise the tempCcell attribute. The value of Temperature at any given point in time is the current tem-perature in degrees Celsius. The tempF is derived from a maintenance rule that usesthe value tempC to perform temperature conversion. The value of tempF is automati-cally recalculated whenever the value of tempC changes. @perform defines a rule that isused to perform non-undoable actions such as output I/O. In this example, a performrule is used to display the values of tempC and tempF.

Lamport CellsLamport Cells [Miller 2003] is a reactive library for E [Miller et al. 2005]. In LamportCells, a reactive program is expressed in terms of reactors and reporters. Reactorssubscribe to receive reports from the reporters, and reporters accept subscriptions andsend reports to the registered reactors.

Reactors may subscribe either to receive at most one report (whenever-reactors) orto receive every report (forever-reactors). The subscription for a whenever-reactor lastsonly until the first report is received. The client may then decide to re-subscribe whenit needs a less stale value. In this respect, the evaluation model is pull-based as theclient re-subscribes to receive a new value only when it is needed. On the other hand,a forever-reactor immediately re-subscribes to continually receive new values. In thisrespect, the evaluation model is push-based. The propagation of changes is unidirec-tional.

Lamport Cells provides support for distributed reactive programming in that thereactor and the reporter may be located on different hosts in a network. In order toprovide support for distribution, subscriptions and reports are sent asynchronouslywith no return values. Lamport Cells tackles the potential space-leak problems, byonly retaining “live” references to each subscribing reactor. However, Lamport Cellsdoes not avoid glitches (neither in a local nor a distributed setting).

The temperature conversion example can be expressed in Lamport Cells as follows.

def tempConverter(){def tempC := makeLamportSlot(Temperature);def tempF := whenever([tempC], fn{tempC * 1.8 + 32}, fn{true});return tempF;

}

The above code defines the tempConverter function. The makeLamportSlot constructcreates a reporter that is then bound to the variable tempC. In this example, the re-porter is initialised with the value of the predefined variable Temperature whose value

ACM Computing Surveys, Vol. , No. , Article , Publication date: 2012.

事前に定義された変数(イベント)に関連づけ

.NET RXの例

➤ 統合⾔語クエリLINQ上に構築された.NET拡張

➤ イベントソースに対して、IObservable<T>というジェネリックインターフェースを提供

➤ IObservable<T>は、イベントオブザーバを登録するためのメソッドSubscribeを提供

➤ push型のモデル

➤ glichに関しては不明(No ? と論⽂に書いてある)

➤ 関数型じゃないリアクティブプログラミング

35

A Survey on Reactive Programming :29

.NET Rx

.NET Rx [Hamilton and Dyer 2010] is a reactive programming extension to .NET.It is built on top of LINQ [Microsoft 2007], a project that adds query facilitiesto the .NET Framework. As in Scala.React, .NET Rx provides a generic interfaceIObservable<T> for representing event sources. The IObservable interface provides amethod Subscribe that enables one to register a closure that will be executed when anevent occurs. In addition, .NET Rx allows event composition. New specific events canbe created from general events using the rich set of LINQ combinators (e.g., aggregate,selection, joins, etc.).

The propagation of events in .NET Rx is based on the push model. Consumers reg-ister interest in particular event types and then the events are pushed to them whenthey occur. This work is still ongoing and from the available documentation it is notexplained if the language achieves glitch freedom.

The temperature conversion example can be realised in .NET Rx as follows.

var temperature = new Temperature();temperature.Subscribe( temp =>

{var tempC = temp.currentTemperature;var tempF = (tempC*1.8)+32;

})

Temperature is a class that implements the IObservable interface and emits eventswhen the current temperature changes. The Subscribe method registers a closure thatis executed for each temperature change event. The closure includes the logic of con-verting the temperature from degrees Celsius to Fahrenheit.

4.3. Synchronous, Dataflow and Synchronous Dataflow LanguagesThere have been programming paradigms that have been used to model (real-time) re-active systems. These include synchronous programming, dataflow programming andsynchronous dataflow programming. In this section, we give a brief review of thoseparadigms because there exist surveys [Benveniste et al. 2003]; [Whiting and Pascoe1994]; [Johnston et al. 2004] that give a full review of the research on the languagesin the family of synchronous programming, dataflow programming and synchronousdataflow programming.

Synchronous programming is the earliest paradigm proposed for the development ofreactive systems with real-time constraints. Synchronous languages are based on thesynchrony hypothesis where reactions are assumed to take no time and are atomic. Itis assumed that a reaction takes no time with respect to the external environment andthat the environment remains unchanged during the execution of the reaction. This as-sumption simplifies programs and can be compiled into efficient finite-state automata,which can be translated into a program in a sequential language [Berry and Gonthier1992]. A number of synchronous languages exist. These include Esterel [Berry andGonthier 1992], StateCharts [Harel and Politi 1998], and FairThreads [Boussinot2006].

Another approach that has been used to model reactive systems is dataflow pro-gramming (originally developed to simplify parallel programming) [Johnston et al.2004];[Whiting and Pascoe 1994]. A dataflow program is expressed as a directed graphwith nodes representing operations and arcs representing data dependencies betweencomputations. The difference between traditional dataflow languages and reactive lan-guages is that in dataflow languages are first-order. Examples of dataflow languagesinclude LabVIEW [Kalkman 1995] and Simulink [The MathWorks 1994].

ACM Computing Surveys, Vol. , No. , Article , Publication date: 2012.

IObservabale<T>を実装したクラス

まとめ

まとめ

➤ リアクティブプログラミングというプログラミングパラダイムを紹介

➤ 1997年に登場と、⾔語のモデルとしては⽐較的新しい

➤ オブジェクト指向:1967年、Simula⾔語

➤ ジェネリックプログラミング:1989年

➤ Musser, D. R.; Stepanov, A. A. (1989). "Generic programming". In P. Gianni. Symbolic and Algebraic Computation:

International symposium ISSAC 1988. Lecture Notes in Computer Science 358. pp. 13–25. doi:

10.1007/3-540-51084-2_2. ISBN 978-3-540-51084-0

➤ イベントを抽象化して記述できる

➤ 複雑なイベントの操作も簡単になるらしい

➤ GUIなどで⼤活躍

37

EOF

38