Topics

・関数型プログラミングとオブジェクト指向のパラダイムとしての対立 国内の【自称】関数型コミュニティと海外の論調の違い

ガラパゴス・ネットスラング=「関数型ポエム」という呪詛、先入観的読書と、フェアなレビューの登場

Qiitaの騒動から派生して、東北大学の住井 英二郎@esumii氏、らくだの卯之助@camloeba氏その他が、犯罪者集団に合流して2ちゃんねるでの誹謗中傷チームの「8賢者」「ウィザード組」とかアホなことをやってる件について

JavaScriptではES6+とReact-JSXからES5へのトランスパイルが標準に / ATOMエディタで最速環境構築 厳選パッケージ 3 + 3 2015年夏バージョン

2016年のnode、ES6、React、Babel、Atomエディタ界隈の方向性

Dockerじゃないsystemd-nspawn+machinectlが非常に良い

99%のプログラマがIQ145のJKに「ダサい」と言われてしまう理由とは?【その1】「計算機科学のほんとうの基礎」を理解していない。IQ145のJKと同じ事を語るMITの権威とSICPという聖典の権威を借りてマインドコントロールを解いてみよう

99%のプログラマがIQ145のJKに「ダサい」と言われてしまう理由とは?【その2】関数型プログラミングのイミュータブルな世界観とイミュータブルな実世界を完全に統合

10年先を行く斬新な関数型(FRP)データベースについて説明する 99%のプログラマがIQ145のJKに「ダサい」と言われてしまう理由とは?【その3】

[React (.js Facebook)解説 関数型プログラミングに目覚めた! IQ145の女子高生の先輩から受けた特訓5日間 サポート記事【静的HTML編】React 解説【動的HTML-FRP編】

量子コンピュータが超高速である原理と量子論とそれに至るまでの科学哲学史をゼロからわかりやすく解説01量子コンピュータが超高速である原理と量子論とそれに至るまでの科学哲学史をゼロからわかりやすく解説02

『関数型プログラミングに目覚めた!』のレビュー(Day-1)について

LISPデータ構造の問題点の指摘と抜本的解法としての新プログラミング言語の策定/純粋関数型言語「SPINOZA」

著書『関数型プログラミングに目覚めた! IQ145の女子高生の先輩から受けた特訓5日間』 [Day1]たち読み記事 無料公開中

『関数型プログラミングに目覚めた! IQ145の女子高生の先輩から受けた特訓5日間』を大変多くの方々にお買い求めいただき、感謝します。本書の全目次を公開し、質問を受け付けます。

2015年7月30日木曜日

nodeのFRP(関数型リアクティブ)ライブラリ`worldcomponent`の後継、`worldtimestream`の公開

nodeのFRP(関数型リアクティブ)ライブラリworldcomponentの後継、worldtimestreamをnpmで公開をしました。

https://www.npmjs.com/package/worldtimestream
https://github.com/kenokabe/worldtimestream

FacebookのJSXで開発テストしており、ライブラリもテストも最終的にバニラJavaScriptへコンパイルしています。

Install

node / io.js

npm install worldtimestream

WebBrowser

https://raw.githubusercontent.com/kenokabe/worldtimestream/master/js/worldtimestream.js

をコピーペースト

Rationale

アイデアは、前回の記事です。

関数型プログラミングと古典物理学の密接な関係

Date.now() はストリームへ透過に参照する時間関数ですが「ユーザの現在時間」が暗黙に引数として渡されているため理解しにくいです。

より物理系と時間という物理量の概念を関数型のコードで明示できるように、FRPライブラリをハックしました。

worldtimestreamは命名したとおり、時間軸上のストリームです。
時間要素に依存しているので、worldtimestreamのストリームは物理量です。

___.world = ___((t) => {
//...........
});

という時間発展の恒等式を宣言することにより、
古典物理学の物理量である時間変数tが得られます。

別に時間変数nowと宣言しても構いませんが、現在時間というのは、なかなか哲学的素養がないと理解しにくい概念であるので、恒等的な値tとして宣言します。

以下、すべて基礎となる上記のスコープ内で記述します。

上記コードにより、

時間発展しているworldtimestreamのストリームの物理系の物理量t

が、↓

時間発展しているユーザが現在実行しているコード

へ恒等的にmapされているので、
t()とすることにより、それぞれの瞬間のユーザは透過にその値を参照できます。

つまりそれが、時間発展している世界のそれぞれの瞬間のユーザにとっての「現在時刻」であるということになります。

たとえば、

 ___.world = ___.log(t());

という恒等式を宣言しておくと、
このコードを意識的に計算するアクションを起こした、すべてのユーザのそれぞれの現在時刻がコンソールへ表示されます。

また、ストリーム___aを宣言しておき、

 var ___a = ___();
  ___.world = ___a.compute(() => {
    ___.world = ___.log(t(), 'a', ___a.t());

  });

と恒等式を宣言しておくと、

時間発展するストリーム___a
「過去」から「未来」方向
あるいは
「未来」から「過去」方向
で変化が生じた瞬間に、ユーザの関与なしに任意のコードを自動計算させることが可能です。

  var f0 = () => {
    ___.world = ___.log('test start');
    ___.world = ___a.appear(0);
  };
  ___.world = t.computeTimeout(f0, 0);

というのは、このコード全体が任意のユーザによって最初に実行された瞬間tにおける、ストリーム___aの値を宣言しています。

 var f = () => {
    ___.world = ___a.appear(___a.t() + 1);

  };

  ___.world = t.computeInterval(f, 1000);

とすることで、そこ瞬間を起点として、ストリームの時間軸上で「未来」方向に1秒間のインターバルの値を宣言しています。

この場合は、ストリーム___aのそのインターバル地点のある時間tにおける値が参照されており、その値に1を加えた値をストリーム___aの未来方向の次の瞬間に現れているという「関係性」を宣言しています。

念の為ですが、ストリーム___aは過去から未来まで時間軸上でイミュータブルで変化しません。ストリーム上に離散する値の関係性が上記コードによって宣言されているだけです。

たとえばこのストリーム___aをオブジェクト参照などで、コピーあるいは「バックアップ」すれば、過去から未来までまったく同じストリームがコピーされます。
つまり、未来方向の任意の時間で、
___aの値がappearされるという宣言があるのならば、まったく同じイミュータブルなストリームである___bもその同時の瞬間に値に「変化」が起こるストリームとして宣言されます。

過去未来の時間軸上で別の運命をもつ別のストリームを作成するには、同様に

var ___b = ___();

というような別個の独立したストリームを宣言します。

もし、この独立したストリーム___bが、
ストリーム___aと関係がある場合は、その都度その関係式を宣言します。

たとえば、
___aのストリーム上のある瞬間の値が、
___bのストリーム上の同一瞬間の値と等しくなり、「未来方向」へはずっとその値のままである、という我々が日常レベルで使う用語としての「値のバックアップ」という関係を宣言したいのであれば、

 ___.world = ___b.appear(a.t());

とすれば簡単に出来ます。

あるいは、

___a___bは、物理量tに依存しない形で、恒等的な関係が存在するとき、

たとえば

___b = ___a x 5
の関係を宣言したい場合は、

  ___.world = ___a.compute((x) => {
    ___.world = ___b.appear(x * 5);
  });

とすれば簡単に宣言できます。

Test

test.jsx

'use strict';

var ___ = require('./worldtimestream.js');

___.world = ___((t) => {

  var ___a = ___();
  var ___b = ___();

  ___.world = ___a.compute(() => {
    ___.world = ___.log(t(), 'a', ___a.t());

  });
  ___.world = ___b.compute(() => {
    ___.world = ___.log(t(), 'b', ___b.t());
  });

  ___.world = ___a.compute((x) => {
    ___.world = ___b.appear(x * 5);
  });

  var f0 = () => {
    ___.world = ___.log('test start');
    ___.world = ___a.appear(0);
  };
  var f = () => {
    ___.world = ___a.appear(___a.t() + 1);
  };

  ___.world = t.computeTimeout(f0, 0);
  ___.world = t.computeInterval(f, 1000);

});

実際に、test.jsxを実行した結果は以下のようになります。

1438234695190 ‘a’ 0
1438234695200 ‘b’ 0
1438234696204 ‘a’ 1
1438234696204 ‘b’ 5
1438234697206 ‘a’ 2
1438234697206 ‘b’ 10
1438234698208 ‘a’ 3
1438234698208 ‘b’ 15
1438234699209 ‘a’ 4
1438234699209 ‘b’ 20
1438234700211 ‘a’ 5
1438234700211 ‘b’ 25
1438234701213 ‘a’ 6
1438234701213 ‘b’ 30
1438234702214 ‘a’ 7
1438234702214 ‘b’ 35
1438234703215 ‘a’ 8
1438234703215 ‘b’ 40

0 コメント:

コメントを投稿

Popular Posts

Blog Archive