時間発展する物理系、つまり、私達が生活するこの宇宙の挙動を、関数型プログラミングでイミュータブルに記述する、という関数型リアクティブプログラミング(FRP)の概念実証をJavaScript言語でしてみましょう。
我々の馴染みの深い「放物線」を例に取ります。
「放物線を描く」と日常的によく使いますが、物理学(日本語)では正確には、「斜方投射」と言います。
斜方投射(しゃほうとうしゃ)とは物体をある初速度をもって空中に投げ出す動作である。空気抵抗が十分小さく無視できる場合、斜方投射された物体の軌跡は放物線を描く
水平方向にx軸、
鉛直上向きにy軸をとります。
初速
偏角
のとき、
斜方投射してからの経過時間 における
物体の速度および座標 は
という恒等式で表せます。(は 重力加速度=9.8 m/ss)
これがニュートン物理学の時間発展する恒等式です。
. タイガー・ウッズの平均ヘッドスピード57.5m/s ボール初速度85.0~86.5m/sと公表されています。
らしいですから、
初速を85.0m/s、偏角30度とし、空気抵抗を無視したゴルフのスーパーショットっぽい斜方投射を上記時間発展する恒等式をそのまま用いて、
worldtimestream
React
を利用して関数型リアクティブプログラミングのコードを書くと以下のようになります。
code
恒等式の宣言
worldtimestream
で、物理系の時間t
をコードに恒常的にマップするworldengineとして宣言しておきます。
___.world = ___((t) => { // world engine
//===========================================================================
});
その中で、恒等式の初期設定が宣言され、
var V0 = 85.0; // m/s
var deg = 30; //degree
var THETA = deg / 180 * Math.PI; //radian
var G = 9.8; //gravity const
恒等式そのものがt
の時間関数coordinateEquation
で宣言されています。
var coordinateEquation = (t) => {
var x = V0 * Math.cos(THETA) * t;
var y = V0 * Math.sin(THETA) * t - G * Math.pow(t, 2);
return {
x: x,
y: y
};
};
これで、すべての関係性は記述されていますが、この時間発展する時間関数の恒等式を実際の画面表示をするための「計算」は一切なされていません。
つまり、ここまでは、物理系と物理量コードのストリームとの関係性が100%抽象世界として宣言されただけで、コンピュータのハードウェアでその関係性の具現化、つまりふたたび、そのストリームが具体的な物理系としての画面に反映する「計算」タイミングなどの指示は行われていません。
計算からの画面描写(画面描写も関係式の計算に他ならない)
この「計算」部分を一手に司るのが、ReactコンポーネントReactComponent
です。
componentWillMount()
において、
var init = () => {
var T0 = t();
var f = () => {
___.world = ___coordinate.appear(coordinateEquation((t() - T0) / 1000));
};
___.world = t.computeInterval(f, 10); //calculate 10milsec resolution
};
___.world = t.computeTimeout(init, 0);
で、___coordinate
というストリームを、10ミリセカンドの解像度をもってt
の時間関数coordinateEquation
で「計算」することを宣言します。
___x={___()} ___y={___()}
というReactが描写するコンポーネントのXY座標に相当する、worldtimestream
のストリームとして定義されたプロパティは、___coordinate
が「計算」されると、適切な画面座標に投影しながら
var com = this;
___.world = ___coordinate.compute((coordinate) => {
___.world = com.props.___x.appear(50 + coordinate.x * Drawscale);
___.world = com.props.___y.appear(300 - coordinate.y * Drawscale);
com.forceUpdate();
});
コンポーネントを再描画します。
このように、FRPライブラリworldtimestream
とReactを利用することで、簡潔に、
時間発展する物理系、つまり、私達が生活するこの宇宙の挙動を、関数型プログラミングでイミュータブルに記述する、という関数型リアクティブプログラミング(FRP)を実現可能です。
___.world = ___((t) => { // world engine
//===========================================================================
//MKS system of units
var ___coordinate = ___();
var V0 = 85.0; // m/s
var deg = 30; //degree
var THETA = deg / 180 * Math.PI; //radian
var G = 9.8; //gravity const
var coordinateEquation = (t) => {
var x = V0 * Math.cos(THETA) * t;
var y = V0 * Math.sin(THETA) * t - G * Math.pow(t, 2);
return {
x: x,
y: y
};
};
//==============================================================
var Drawscale = 4; //4 dot = 1 meter
var ReactComponent = React.createClass(
{
componentWillMount() {
var com = this;
___.world = ___coordinate.compute((coordinate) => {
___.world = com.props.___x.appear(50 + coordinate.x * Drawscale);
___.world = com.props.___y.appear(300 - coordinate.y * Drawscale);
com.forceUpdate();
});
var init = () => {
var T0 = t();
var f = () => {
___.world = ___coordinate.appear(coordinateEquation((t() - T0) / 1000));
};
___.world = t.computeInterval(f, 10); //calculate 10milsec resolution
};
___.world = t.computeTimeout(init, 0);
},
render() {
var com = this;
var el = (
<div>
<h1>For new shot, Just Reload the browser page</h1>
<svg height = "100%" width = "100%">
<circle r="5" fill="blue"
cx = {this.props.___x.t()}
cy = {this.props.___y.t()}/>
</svg>
</div>
);
return el;
}
});
var mount = React.render(<ReactComponent ___x={___()} ___y={___()} />, document.body);
//==============================================================
//===========================================================================
});
0 コメント:
コメントを投稿