reactive-webを試してみました

Liftを使ったRIAフレームワーク reactive-web を試してみました。RIAフレームワークと言っているわりには、今のところGUI部品がそろっているわけではなく、ブラウザとサーバサイドで簡単にイベントをやりとりするためのフレームワークのようだ。とりわけJavaScriptの隠蔽っぷりがお見事だと思いました。

Github: nafg / reactive
Googleグループ Lift: reactive-web

動作確認は簡単で、

> git clone http://github.com/nafg/reactive.git
> cd reactive
reactive > sbt update
reactive > sbt "project demo" jetty

localhost:8080にアクセスする。



何が起きてるのかさっぱりわからないけれど、とりあえず、ブラウザ上のキーイベントがすぐにサーバサイドに伝わったり、サーバーサイドのイベントがブラウザに伝わったりする様子がわかる。
このリポジトリの構成は、

reactive
(reactive-core)
Functional Reactive Programming (FRP) ライブラリ
reactive-webLiftweb向けのCometActorとSnippetフレームワーク(各DOM部品など)
reactive-web-demoLiftwebのサンプルアプリ

reactive-web-demo はソースが短くて簡単なので、マネしながらページを追加していってみる。

Boot.scalaで、"reactive.web.Reactions.initComet"とCometActorを起動していることに注意。

※全コードはgistに貼りました

サーバサイドタイマーがクロックアップするたびにブラウザに現在時刻を表示する。

■テンプレート

<lift:surround with="default" at="content">

  <div class="lift:reactive" /><!-- 必須:JavaScript等に展開される -->

  <!-- CSS Selector Snippet (Lift2.2 or later) -->
  <div class="lift:ClockCSSSnippet">
    <span id="clock" />
  </div>
</lift:surround>

■スニペット

class ClockCSSSnippet extends ReactiveSnippet {
 val clockES = new Timer(interval = 1000,
            cancel = ()=> !isPageAlive)
 val clockSig = clockES.hold(0L)
 val clockSpan =
   Span( clockSig.map( t => Text((new Date).toString )) )

  def render = "#clock" #> clockSpan
}

Lift2.1以前のSnippetの作法なら、差分は以下のようになる。

<!-- Old Snippet -->
<lift:clockOldSnippet >
  <ns:clock />
</lift:clockOldSnippet >

class ClockOldSnippet extends ReactiveSnippet{
    :
  def render(xhtml:NodeSeq) :NodeSeq =
   bind( "ns", xhtml, "clock" -> clockSpan )
}

ブラウザからの入力をサーバサイドに伝播して、ブラウザにエコーする


■テンプレート
<lift:surround with="default" at="content">
  <div class="lift:reactive" />

  <div class="lift:EchoSnippet">
    <input id="field" /><br />
    エコー: "<span id="echo"/>"<br />
  </div>

</lift:surround>

■スニペット

class EchoSnippet extends ReactiveSnippet {
  val field = TextInput()
  field.value updateOn field.keyUp

  val fieldValue = field.value.value map { v =>
    println( "field value on client:"+v )
    Text(v)
  }
  println( fieldValue ) //MappedSignal

  val echo = Span( fieldValue )

  def render =
    "#field" #> field &
    "#echo" #> echo
}

これだけのコードで??と、けっこう驚きました。JavaScriptがうまく隠蔽されていて、JSを使ってるという意識すらないかも。
これでいろんなHTMLElementやGUIのバリエーションが増えたら面白いかもしれないですね。

Functional Reactive Programming

このフレームワークのベースになっているFunctional Reactive Programmingという言葉を初めて知ったので、今後勉強しておきたい。

参考文献:
http://en.wikipedia.org/wiki/Reactive_programming
http://en.wikipedia.org/wiki/Functional_reactive_programming
maoeのブログ:やさしいFunctional reactive programming(概要編)
maoeのブログ:やさしいFunctional reactive programming(Event編)
maoeのブログ:やさしいFunctional reactive programming(Behavior編)

とても自分にはまとめられませんが、、、
「シグナルに反応するもの」というのが、reactive-webの例ではSpan( signal )などということなのだろうか。。

reactive-core を使っていろいろ試せそうです。

reactive> cd reactive-core
reactive-core> sbt

とりあえずテストを動作確認

> test
[info] == test-finish ==
[info] Passed: : Total 28, Failed 0, Errors 0, Passed 28, Skipped 0
[info]
[info] All tests PASSED.
[info] == test-finish ==
[success] Successful.

テストコードを見ながら確認。
元のSignalを変更すると、それに反応して関連するSignalも変更されることがわかる。

> console
scala> import reactive._

scala> val v = Var(1)
scala> val signal = v.map[Int,Signal[Int]]( _ * 3 )
scala> val signal2 = signal.map[Int,Signal[Int]]( _ * 100 )
scala> v.now // => 1
scala> signal.now // => 3
scala> signal2.now // => 300
scala> v()=123
scala> signal.now // => 369
scala> signal2.now // => 36900

同じカテゴリのエントリ
1.Lift再入門 / 8.javascriptからsubmitできない / 7.Ajax Form / 6.Radio、Checkboxについて / 5.行列型の編集FORM / 4.サーバーサイドバリデーションとサーバサイド関数 / 3.ログインFORM - S.param使ったら負け / 2.Snippetメソッドとして許される型 / sbt0.12.xで依存jar抽出タスク / scala2.10+lift2.5+NetBeans7.2 / Scalaで入門関数プログラミング / reactive-webを試してみました / Lift2.2M1のテンプレート機能 / Scala Compiler Plugin / View Bound/Context Bound / ScalaZa01参加してきました / Akka Frameworkチュートリアルの次 / Akka Frameworkチュートリアルその2 / Akka Frameworkチュートリアル / LiftでJCaptcha / Url Rewrite Filter / sbt-android-plugin / Android SDK for Scala / 祝Lift2.0リリース / Liftの携帯対応まとめ / Scala2.8への移行 / Lift 2.0-scala280-SNAPSHOT/sbt0.7.1 / Scalaお絵かき環境 - Kojo / Lift+Quartzでバッチ / Scala&Liftを採用した理由 / Liftでdate_select系ヘルパーを作る / LiftでAjax / LiftのSubmitかしこい / lift-mapperのpaginateを使う / snippetをspecする / Lift Mapperを拡張する / LiftのDBをMySQLに / Liftプロジェクト環境を整える / Scala本読み比べてみました / NetBeans6.7&scala / じつはScalaはライトな言語 / Scalaバザ~ル / lift1.0所感 / specsを読む / implicit def / ScalaならNetBeansがサイコー / scala勉強会@東北がスタート / それでも俺はLiftをやるってのか / Scala&Liftセットアップ / ブログリニューアル /
コメント

コメントしてください

closed.