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年12月11日金曜日

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

この半年で、node、ES6、React、Babel、Atomエディタ界隈に結構な変化があり、
JavaScriptではES6+とReact-JSXからES5へのトランスパイルが標準に / ATOMエディタで最速環境構築 厳選パッケージ 3 + 3 2015年夏バージョン
で紹介したAtomエディタの環境構築の方法で、いま自身の環境をアップデートするにやると普通にコケてしまう、いろいろ不具合が出るので更新。

ES、JSXトランスパイラのデファクトスタンダードであるBabel公式サイトの掲示板で、Babel開発者とやりとりした情報をベースに自分自身忘れないようにメモを兼ねて情報共有しておきます。

https://discuss.babeljs.io/t/error-parsing-jsx-with-global-installation-babel-preset-react/59

JavaScriptは本格的にECMASCript 6(ES6)へ移行した

実際使い込めば使い込むほどES6は強力。

2013年に、
調査: もっとも表現力に富んだ汎用プログラム言語は Clojure,CoffeeScript,Haskellというのがあった。

CoffeeScript (#6) は JavaScript (#51) よりもはるかに高い表現力を示している。事実上,すべての言語の中での最高値である。

一貫性においても CoffeeScript が変わらず No.1 であるが,4番目の Clojure と比較した IQR (interquartile range,,四分位範囲) の差異はわずか23LOC/コミットに過ぎない。

というように、CoffeeScriptの表現力はプログラム言語の中でも際立っており、素のJavaScriptは比較すると随分と劣っていた。

しかしそのJavaScriptもまさにそのCoffeeScriptが獲得していた表現力を吸収するようにES6となり、標準化は正義ということで、CoffeeScriptの役割は終わったように思う。
JavaScriptはES6になり、もっとも表現力の高い言語に進化したと言っても過言でないと思うし、実際コーディングしていて関数型プログラミングの特性が発揮するように表現力が高まった実感がある。

以下、
Trending repositories
https://github.com/trending?l=javascript&since=monthly
のトレンドも踏まえる。

Node.js

 
Node.jsの運営問題による開発の遅れから分裂していたio.jsはめでたく、Node.jsの体制を修正しながら本家に再統合。
Node v4.0.0となり、
矢継ぎ早に、Node v5.0.0のラインもリリースされた。

io.jsをマージ、ES6サポートを実現した「Node.js 4.0」リリース

https://nodejs.org/en/docs/es6/

ようやく、NodeでもECMASCript 6(ES6)が本格的にサポート開始。

つけくわえておくと、
https://github.com/Automattic/wp-calypso
というプロジェクトもトレンドにあるが、
Calypso is the new WordPress.com front-end
ということで、WordPressのコンテンツエンジンもPHPからNodeベースになるのか、なったのか詳しいことはまったく調べていないので、あまり良く知らない。

ReactはDOMと分離された

ReactはあいかわらずクライアントサイドのUIで確固たる位置を占めており勢力を拡大しているように見える。

Reactは、もはやHTML専用のUIエンジンではない、ということで、
React DOMは本体Reactから分離された。

http://facebook.github.io/react/blog/2015/10/07/react-v0.14.html

React has nothing to do with browsers or the DOM.
ReactはブラウザともDOMとも関係ない

Major changes

Two Packages: React and React DOM
As we look at packages like react-native, react-art, react-canvas, and react-three, it has become clear that the beauty and essence of React has nothing to do with browsers or the DOM.

To make this more clear and to make it easier to build more environments that React can render to, we’re splitting the main react package into two: react and react-dom. This paves the way to writing components that can be shared between the web version of React and React Native. We don’t expect all the code in an app to be shared, but we want to be able to share the components that do behave the same across platforms.

つまり、2014-2015年に、一部、日本国内で、Reactとは仮想DOMのことである、というような喧伝がなされていたが、実は仮想DOMは本質ではなく、DOMが仮想化されている大元となる理由、コンポーネント指向、至高、つまりUIがオブジェクト指向ではなく関数型プログラミングを体現していることがより明確になった。

Functional Stateless Components in React 0.14
https://medium.com/@joshblack/stateless-components-in-react-0-14-f9798f8b992d#.nsecgw6kw

React Native

http://facebook.github.io/react/blog/2015/10/07/react-v0.14.html

This paves the way to writing components that can be shared between the web version of React
and React Native.

とあるように、背景にはやはりReact Nativeの存在が大きい。

https://github.com/facebook/react-native

ReactNativeは以前から存在していたが、iOSのみサポートしており、今や世界のスマホOSのマジョリティであるAndroidがサポートされていなかった。Reactバージョン0.14でDOMとの分離の方向性が打ち出されるとほぼ同時期に、Androidのサポートもリリースされて、今後スマホのUI開発でもReactのコンポーネント指向(関数型)も本格化すると思われる。
 
Reactで書かれたUIコードは、
Webブラウザでは、ReactDOM
スマホでは、ReactNative
に接続され、共用できる。

Babel

Nodeが、ES6を本格的にサポート開始したことにより、ES6+→ES5トランスパイラであるBabelのJavaScript世界における重要性は薄まったが、

1 JavaScript世界のUIデファクトであるReactの言語JSXを広範なブラウザで稼働するES5へのトランスパイラするにために、FacebookはBabelプロジェクトに依存する方針を明確にしており(前回記事参照)、Reactクライアントサイドをトランスパイルする為には、今後も末永くBabelは必須。

2 NodeのES6+対応はまだまだ発展途上。ES6で有用な仕様に開発途上オプションフラグを指定しなければいけないなど未熟。それに比べてBabelは現行、ES6+の対応度に勝る。
https://kangax.github.io/compat-table/es6/

1,2より、Babelは今後もデファクトのトランスパイラとして活躍し、JSコミュニティ(Facebook/React含む)から幅広い支持がありそうな状況。
ボトムラインとして、事実、これまでNodeはio.jsと分裂したり、大元のV8エンジンのES6対応が遅々として進んでないようだったり大きな問題があった。それに比較してBabelプロジェクトはフットワークが軽く対応が早く、この2015年に、JavaScriptコミュニティがES6への移行することを強く後押した功績も大きいと思う。

Babelとnpmのプロジェクトローカル指向

近頃、Nodeのパッケージマネージメントシステムであるnpmは3系に、Babelは6系にメジャーバージョンアップした。

npmも、Babelプロジェクトも、パッケージ依存は、Babelのようなツールも含めてプロジェクトローカルに分離独立させておくべきだ、という方針を強めている。

これはJavaScript、Node世界が、洗練された形で進化する過程で不可避に複雑化されて、必要なツールが増えてくると、各ツールとプロジェクトのバージョンの整合性が問題となってくる。

これまで多くの場合、ツールは、npm install -g などとし、ツールはグローバルにインストール、各プロジェクトから共用する、という発想だったのが、もうその方向性では行き詰まるので、各プロジェクトローカルにそれぞれ専用のバージョンでインストールしよう、という方向性になっている。

もちろん各パッケージにいちいち巨大なツールを含有していたら、複数のnpmパッケージに依存するプロジェクト全体がとんでもないことになるのだが、npmにはdevDependenciesという仕組みで、パッケージ配布時には自動ではインストールされることがない開発モードの依存パッケージという秀逸な仕組みがあるので、それでうまく整理できる。

しかしこれまでいまいち意味がよくわからなかったのが、
Babelの公式サイトのドキュメントで、

http://babeljs.io/docs/setup/#babel_cli
 
Installation

$ npm install -g babel-cli

とあくまでグローバルインストールを公式に推奨しているように見えた。

しかし、Babel6系にアップデートした上で、
JavaScriptではES6+とReact-JSXからES5へのトランスパイルが標準に / ATOMエディタで最速環境構築 厳選パッケージ 3 + 3 2015年夏バージョン
のとおり、環境構築をしていくと、BabelのJSXのトランスパイルでエラーがでてコケる。

どうしようもないので、
Babel公式サイトの掲示板で質問してみたところ、
https://discuss.babeljs.io/t/error-parsing-jsx-with-global-installation-babel-preset-react/59

この理由は結局、そもそも公式ドキュメントのSetupにしたがってBabelをグローバルにインストールするのが間違いで、プロジェクトローカルに、

$ npm install --save-dev babel-cli

とdevDependenciesとしてインストールすべきである、Babelプロジェクト開発者はそういう方針である、ということがわかった。ドキュメントと方針に齟齬があるのは、今現在ドキュメントを大改定中であり、まだ追いついていないということ。

thejameskyle

I’ve been wanting to update the documentation to say otherwise. I just haven’t gotten to it (I’m busy writing the babel handbook right now which does teach people to install locally).

Again, I want to, but I also want to rewrite most of the documentation, a lot of which is in progress.

結局、よほどのことがない限り、原則、ツールも各プロジェクトローカルにdevDependenciesとしてインストールしてしまう

$ npm install --save-dev eslint babel-cli babel-preset-es2015 babel-preset-react webpack

などとし、結果、たとえば公開している自作npmパッケージtimeengine

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

では、

https://github.com/kenokabe/timeengine/blob/master/package.json

{
  "name": "timeengine",
  "version": "4.6.0",
  "description": "Time Engine is the True Functional Reactive Programming Library from the Point of View of Physics, our World and Time",
  "main": "timeengine.js",
  "scripts": {
    "test": "babel timeengine.es -o timeengine.js; babel-node test.js"
  },
  "devDependencies": {
    "babel-cli": "^6.3.15",
    "babel-preset-es2015": "^6.3.13",
    "babel-preset-react": "^6.3.13",
    "eslint": "^1.10.3",
    "immutable": "*"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/kenokabe/timeengine.git"
  },
  "keywords": [
    "FRP",
    "functional",
    "reactive",
    "time",
    "physics",
    "mathematics",
    "stream",
    "sequence",
    "event"
  ],
  "author": "Ken Okabe",
  "license": "MIT",
  "bugs": {
    "url": "https://github.com/kenokabe/timeengine/issues"
  },
  "homepage": "https://github.com/kenokabe/timeengine#readme"
}

と、以下抜粋するように、devDependenciesとして開発ツールをプロジェクトローカルにインストールしてしまうのが最終的な方針と解決策である。

  "devDependencies": {
    "babel-cli": "^6.3.15",
    "babel-preset-es2015": "^6.3.13",
    "babel-preset-react": "^6.3.13",
    "eslint": "^1.10.3",
    "immutable": "*"
  },

この際、

babelコマンドは、プロジェクトローカルの
./node_modules/.bin にインストールされる。

グローバルでインストールしていたときのように、コマンド単体のパスは通っておらず、以上の相対パスをいちいち叩くのは骨が折れ現実的ではにないので、シェルの初期設定に、

.zshrc

export PATH=$PATH:./node_modules/.bin

などとしておけば良い。

その他

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

で示した、

.eslintrcというESLint設定ファイルに以下の内容をコピペし、ホームディレクトリ直下に新規作成します。

{
  "parser": "babel-eslint",
  "env": {
        "es6": true,
        "node": true,
        "browser": true
  },
  "rules": {
   "semi": [2, "always"],
   "strict": 1,
   "no-undef" : 2
  }
}

というのは、グローバルでなくプロジェクトローカルにまとめる方針になるので以下のように更新。

https://github.com/kenokabe/timeengine
のとおり、

.babelrc
.eslintrc
ともに、プロジェクトローカルのファイル郡に含めてしまう。

https://github.com/kenokabe/timeengine/blob/master/.babelrc

{
  "presets": ["es2015","react"]
}

https://github.com/kenokabe/timeengine/blob/master/.eslintrc

{
  "env": {
        "es6": true,
        "node": true,
        "browser": true
  },
  "ecmaFeatures": {
        "jsx": true
  },
  "rules": {
        "semi": [1, "always"],
        "strict": [2, "function"],
        "no-undef" : 2
  }
}

以上のような設定では、前回のように

babel-eslintをインストールすることは不要となった。

Atomエディタ

Atomのプラグインは、

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

と同じ。

2015年8月21日金曜日

加速するJavaScript開発界隈 今、注目を集めるGitHubレポ・ npm ライブラリ 5選

筆者も時折、npmライブラリを公開していますが、

timeengine / Time Engine FRP ( Functional Reactive Programming / 関数型リアクティブ プログラミング) npmライブラリの公開

https://www.npmjs.com/package/timeengine

今、npm(node.js)の公開ライブラリ数が加速的に増加しており、物凄いことになっています。

CodeZine Node.js/JavaScriptの情報収集手段 ~変化が激しいOSSは、直接GitHubをウォッチするより引用

だいたいこのグラフで見ると、1年で2倍になっており、文字通り、指数関数的に増加している様相です。

また、ここ数年、GitHubでホストされているプロジェクトの言語でJavaScriptが1位です。

ここ最近、注目を集めているnpmライブラリ、GitHubに公開されているプロジェクトを示します。

JAWS: The Server-less Stack

https://github.com/jaws-stack/JAWS

今GitHub@JavaScript界隈で一番注目されているプロジェクト。
著書でもちらっと触れた、関数型クラウドサービス、 Amazon Web Services Lambda Functionsを利用したアプリケーションスタック。

JavaScriptで関数型プログラミングやるのがそもそも適していない、などなど一部国内の界隈で眠いことを言う方々を尻目に、Amazonクラウド環境でホストされるJavaScriptの関数のみをコールしてWebアプリケーションのバックエンドを構築するという次世代アプリケーションスタック。

Goals:

  • Use No Servers: Never deal with scaling/deploying/maintaining/monitoring servers again.
  • Isolated Components: The JAWS back-end is comprised entirely of AWS Lambda Functions. You can develop/update/configure each separately without affecting any other part of your application. Your app never goes down… only individual API routes can go down.
  • Scale Infinitely: A back-end comprised of Lambda functions comes with a ton of concurrency and you can easily enable multi-region redundancy.
  • Be Cheap As Possible: Lambda functions run only when they are called, and you only pay for when they are run.

ということで、

とにかくクラウドでもなんでも自サーバーを保持しないので、いろんな面倒から解放される(はず)だ、

とにかく隔離されたコンポーネントだ、関数型のAWSラムダ関数だ、サーバーはないので落ちることはない、

無限にスケールする、マルチリージョンのコンカレントの関数だ、

関数コール分の従量制課金なので、コスパ最強のはずだ、

という、まさに次世代クラウドコンピューティング全開のWebアプリケーションの未来像が提示されています。

個人的には、まだ時期尚早、というか時間が加速しているので、そのうちすぐ検討しなければいけないのかな、という予感もありますが、今のところはAzureクラウドで快適なので、やはり人柱になるには現在の時間スケールで早熟すぎるという印象で、正直まだ面倒臭い感じがします。ただ時流に乗りまくってるビジョナリー、パイオニア達が一定数存在しており、やはり時間が加速している雰囲気をひしひしと感じています。

dragula

http://bevacqua.github.io/dragula/

GoogleKeepみたいな軽快なドラッグUIのライブラリ
ドラッグとドラキュラでドラグラというネーミング。

オフィシャルのReactコンポーネントのブリッジもある。

https://github.com/bevacqua/react-dragula

Reactはすでに業界標準。これは普通に使える。

algebra.js

http://algebra.js.org/
https://github.com/nicolewhite/algebra.js

Build, display, and solve algebraic equations in JavaScript.

代数の方程式を書いたり、LaTeX表示にも対応して表示したり、解くライブラリ。

Mathematicaみたいな大掛かりなものでなく、こういう基本的で簡潔なライブラリは今後何気に重宝しそう、と個人的に思いました。

Professor Frisby’s Mostly Adequate Guide to Functional Programming

https://github.com/DrBoolean/mostly-adequate-guide

JavaScriptの関数型プログラミング教本。

GitHubはもはやコードのプロジェクトだけではなく、書籍(Eブック)の発表の場としても活用されている。

Summary

軽妙な語り口とイラストで内容も非常に濃密で品質が高く必読。

ライセンスは、CC BY-SA 4.0。こんなものがクリエイティブ・コモンズのライセンスででGitHubに無料でポンポンと(すべてのプロジェクトは開発者、筆者が心血を注いだ結晶(自分がそうだからわかる)だが、客観的事象としては加速しすぎていてそのようにしか見えない)UPされている時代になっている。

You Don’t Know JS (book series)

https://github.com/getify/You-Dont-Know-JS
https://www.kickstarter.com/projects/getify/you-dont-know-js-book-series

同じく、GitHubにUPされているCC3-BY-NC-ND ライセンスの無料で読めるJavaScript本。

http://www.amazon.co.jp/You-Dont-Know-JS-Going-ebook/dp/B00V20DQU8

AmazonKindle版でも無料。

先ほどの関数型本もそうだが、他のGitHubプロジェクト同様にIssueがあり、

https://github.com/getify/You-Dont-Know-JS/issues

タイポはもちろん校正が集合知によって為されていくという、出版物とWikiの垣根も曖昧になってきたという趨勢。

すでにここにある未来

とにかく、レイ・カーツワイルの収穫加速の法則でシンギュラリティに向けて邁進する塩梅がどんなものか、一番「身近で手軽に」感じられるのがGitHubのJavaScript関連のレポジトリーやnpmライブラリ界隈だと思います。

2015年8月20日木曜日

timeengine / Time Engine FRP ( Functional Reactive Programming / 関数型リアクティブ プログラミング) npmライブラリの公開

timeengine / Time Engine FRP ( Functional Reactive Programming / 関数型リアクティブ プログラミング) npmライブラリの公開
worldcomponent
worldtimestream
のコンセプトを継承したライブラリです。
https://github.com/kenokabe/timeengine
https://www.npmjs.com/package/timeengine

timeengine

Time Engine is the True Functional Reactive Programming (FRP) Library from the Point of View of Physics, our World and Time
NPM version DownloadsDependency statusDev Dependency statusnpm
NPM

The World, Time, Physics, Mathematics, Equations, and Functional Reactive Programming

JavaScriptで時間発展する物理系=私達が生活するこの宇宙の挙動を、関数型プログラミングでイミュータブルに記述する、という関数型リアクティブプログラミング(FRP)の概念実証
から再掲/
時間発展する物理系、つまり、私達が生活するこの宇宙の挙動を、関数型プログラミングでイミュータブルに記述する、という関数型リアクティブプログラミング(FRP)の概念実証をJavaScript言語でしてみましょう。
我々の馴染みの深い「放物線」を例に取ります。
「放物線を描く」と日常的によく使いますが、物理学(日本語)では正確には、「斜方投射」と言います。
斜方投射(しゃほうとうしゃ)とは物体をある初速度をもって空中に投げ出す動作である。空気抵抗が十分小さく無視できる場合、斜方投射された物体の軌跡は放物線を描く
enter image description here
水平方向にx軸、
鉛直上向きにy軸をとります。
初速 
偏角 
のとき、
斜方投射してからの経過時間   における
物体の速度および座標


という恒等式で表せます。(は 重力加速度=9.8 m/ss)
これがニュートン物理学の時間発展する恒等式です。
. タイガー・ウッズの平均ヘッドスピード57.5m/s ボール初速度85.0~86.5m/sと公表されています。
らしいですから、
初速を85.0m/s、偏角30度とし、空気抵抗を無視したゴルフのスーパーショットっぽい斜方投射を上記時間発展する恒等式をそのまま用いて、
timeengine
Reactを利用して関数型リアクティブプログラミングのコードを書くと以下のようになります。

//MKS system of units
var V0 = 85.0; // m/s
var DEG = 30; //degree
var THETA = DEG / 180 * Math.PI; //radian
var G = 9.8; //gravity const

//10msec time resolution
//t seconds elapsed since t0
var t = __.intervalSeq(10).tMap((tt, t0) => (tt - t0) / 1000);

var x = t.tMap((t) => V0 * Math.cos(THETA) * t);

var y = t.tMap((t) => V0 * Math.sin(THETA) * t - 1/2 * G * Math.pow(t, 2));
The full code is represented at the bottom of this document.

Live Demo

http://sakurafunctional.github.io/demo/react-physics/

Basic

The only API you get to know is tMap.
tMap maps a time-sequence to another time-sequence.
Time Engine is all about tMap.

Reactive Programming in JavaScript

var x = __(); // time sequence
var y = x.tMap((x) => x * 2); // y = x * 2

x.t = 3;
console.log(x.t); //3
console.log(y.t); //6

x.t = 5;
console.log(x.t); //5
console.log(y.t); //10

Declarative code like Math equation and Single (no duplicate) update by automatic dependency resolution

var a = __();
var b = __([a]).tMap(([a]) => a * 2); // b.t = 1 * 2 = 2
var c = __([a, b]).tMap(([a, b]) => a + b * 3); // c.t = 1 + 2 * 3 = 7
var d = __([b]).tMap(([b]) => b * 100); // d.t = 2 * 100 = 200
var e = __([a, b, c, d]).tMap(([a, b, c, d]) => a + b + c + d); //210

a.t = 1; // a is updated, and the whole equations will be evaluated.

Atomic update using Promise

var atomic = __([a, b, c, d, e])
  .tMap(([a, b, c, d, e]) => ({
      a,
      b,
      c,
      d,
      e
  }));

var timeseq10 = atomic.tMap((val) => {
  __.t = __.log('atomic', val);
});

Promise

var m = __();
var n = __();
var o = __();
var p = __([m, n, o]).tMap(() => 'Promised');

var timeseq15 = __.timeoutSeq(6000)
  .tMap(() => m.t = 'some');
var timeseq16 = __.timeoutSeq(7000)
  .tMap(() => n.t = 'time');
var timeseq17 = __.timeoutSeq(8000)
  .tMap(() => o.t = 'other');

var timeseq18 = __.timeoutSeq(10000)
  .tMap(() => m.t = 'some');
var timeseq19 = __.timeoutSeq(11000)
  .tMap(() => n.t = 'time');
var timeseq20 = __.timeoutSeq(12000)
  .tMap(() => o.t = 'other');

var timeseq21 = m.tMap((m) => {
  __.t = __.log({
    m
  });
});

var timeseq22 = n.tMap((n) => {
  __.t = __.log({
    n
  });
});

var timeseq23 = o.tMap((o) => {
  __.t = __.log({
    o
  });
});

var timeseq24 = p.tMap((p) => {
  __.t = __.log({
    p
  });
});

Install

node / io.js

$ npm install timeengine

WebBrowser

ES5 native

include
https://github.com/kenokabe/timeengine/blob/master/timeengine.js
then
<script type="text/javascript" src="./timeengine.js"></script>

ES6 with Babel transpiler

https://babeljs.io/
include
https://github.com/kenokabe/timeengine/blob/master/babel-browser.js
https://github.com/kenokabe/timeengine/blob/master/timeengine.jsx
then
<script src="./babel-browser.js"></script>
<script type="text/babel" src="./timeengine.jsx"></script>

Test

$ npm test
equivalent to
$ babel timeengine.jsx -o timeengine.js; babel-node test.jsx

test.jsx

(() => {
  'use strict';

  var __ = require('./timeengine.js');

  __.t = __.log('test.jsx started...');

  //Reactive and Declarative code ===============
  var x = __(); // time sequence
  var y = x.tMap((x) => x * 2); // y = x * 2
  x.t = 3;
  console.log(x.t); //3
  console.log(y.t); //6

  x.t = 5;
  console.log(x.t); //5
  console.log(y.t); //10

  /*
    //comment out, dependency Error occures here
    //since y depends on x, this is an illegal operation

    y.t = 100;
    console.log('>>>>>>>>>>>>>>>>>>>>>>>>>>>>>' + x.t);
    console.log('>>>>>>>>>>>>>>>>>>>>>>>>>>>>>' + y.t);
  */

  //store values on timeStamps ==============

  var i = __(true); //store flag = true
  var j = __([i], true).tMap(() => i.t * 2); // j = i * 2

  i.t = 3;
  console.log(j.t); //6

  i.t = 5;
  console.log(j.t); //10

  // seq can be operated just like vanilla JavaScript Array
  __.t = __.log('i.length', i.length);

  i.map((val) => {
    __.t = __.log('i.t', val); // 3, 5
  });

  j.map((val) => {
    __.t = __.log('j.t', val); //6, 10
  });

  var timestamp_i0 = i.TimestampOnIndex(0);
  var timestamp_i1 = i.TimestampOnIndex(1);
  var timestamp_j0 = j.TimestampOnIndex(0);
  var timestamp_j1 = j.TimestampOnIndex(1);

  __.t = __.log(i.T(timestamp_i0)); //3
  __.t = __.log(i.T(timestamp_i1)); //5
  __.t = __.log(j.T(timestamp_j0)); //6
  __.t = __.log(j.T(timestamp_j1)); //10


  //==============================================

  //------------------------
  var timeseq0 = __
    .timeoutSeq(500, true) // store === true
    .tMap((t) => {
      __.t = __.log('--------------------------------------------');
      return t;
    });

  var timeseq1 = timeseq0.tMap((t) => {
    __.t = __.log('timeseq0.t', t);
    __.t = __.log('stored to arrray', timeseq0[0]); // same val
  //stored to the seq array
  });

  var f = (tt, t0) => {
    __.t = __.log('t0', t0);
    __.t = __.log('tt', tt);
  };
  var timeseq2 = __.timeoutSeq(1000).tMap(f);
  var timeseq3 = __.timeoutSeq(2000).tMap(f);

  //------------------------

  var timeseq4 = __.timeoutSeq(2500)
    .tMap(__.log('-------------------------------------------'));

  // Single (no duplicate) update by dependency analysis
  var a = __();
  var b = __([a]).tMap(([a]) => a * 2); // b.t = 1 * 2 = 2
  var c = __([a, b]).tMap(([a, b]) => a + b * 3); // c.t = 1 + 2 * 3 = 7
  var d = __([b]).tMap(([b]) => b * 100); // d.t = 2 * 100 = 200
  var e = __([a, b, c, d]).tMap(([a, b, c, d]) => a + b + c + d); //210

  var timeseq5 = a.tMap((a) => {
    __.t = __.log({
      a
    });
  });

  var timeseq6 = b.tMap((b) => {
    __.t = __.log({
      b
    });
  });

  var timeseq7 = c.tMap((c) => {
    __.t = __.log({
      c
    });
  });

  var timeseq8 = d.tMap((d) => {
    __.t = __.log({
      d
    });
  });

  var timeseq9 = e.tMap((e) => {
    __.t = __.log({
      e
    });
  });

  // Atomic update using build-in Promise mechanism

  var atomic = __([a, b, c, d, e])
    .tMap(([a, b, c, d, e]) => ({
        a,
        b,
        c,
        d,
        e
    }));

  var timeseq10 = atomic.tMap((val) => {
    __.t = __.log('atomic', val);
  });

  var timeseq11 = __.timeoutSeq(3000)
    .tMap(() => a.t = 1);

  var timeseq12 = __.timeoutSeq(3500)
    .tMap(__.log('--------------------------------------------'));


  var timeseq13 = __.timeoutSeq(4500)
    .tMap(() => a.t = 5);

  //---------------------------------------------
  var timeseq14 = __.timeoutSeq(5000)
    .tMap(__.log('--------------------------------------------'));


  //Promise---------------------------------------------

  var m = __();
  var n = __();
  var o = __();
  var p = __([m, n, o]).tMap(() => 'Promised');

  var timeseq15 = __.timeoutSeq(6000)
    .tMap(() => m.t = 'some');
  var timeseq16 = __.timeoutSeq(7000)
    .tMap(() => n.t = 'time');
  var timeseq17 = __.timeoutSeq(8000)
    .tMap(() => o.t = 'other');

  var timeseq18 = __.timeoutSeq(10000)
    .tMap(() => m.t = 'some');
  var timeseq19 = __.timeoutSeq(11000)
    .tMap(() => n.t = 'time');
  var timeseq20 = __.timeoutSeq(12000)
    .tMap(() => o.t = 'other');

  var timeseq21 = m.tMap((m) => {
    __.t = __.log({
      m
    });
  });

  var timeseq22 = n.tMap((n) => {
    __.t = __.log({
      n
    });
  });

  var timeseq23 = o.tMap((o) => {
    __.t = __.log({
      o
    });
  });

  var timeseq24 = p.tMap((p) => {
    __.t = __.log({
      p
    });
  });

  var timeseq25 = __.timeoutSeq(13000)
    .tMap(__.log('--------------------------------------------'));

  var f99 = () => {
    __.t = __.log('Any Event Function can be wrapped.');
  };
  __.t = __.wrap(setTimeout)(f99, 14000);
  //onMousemove or whatever instead of setTimeout

  ///-----------------------------------------------

  var timeseq26 = __.timeoutSeq(15000)
    .tMap(() => {
      __.t = __.log('--------------------------------------------');

      var timeseq27 = __
        .intervalSeq(1000)
        .tMap((tt, t0) => (tt - t0) / 1000)
        .tMap((tt) => {
          __.t = __.log(tt);
          return tt;
        });

    });

})();

result

> babel timeengine.jsx -o timeengine.js; babel-node test.jsx

test.jsx started...
3
6
5
10
6
10
i.length 2
i.t 3
i.t 5
j.t 6
j.t 10
3
5
6
10
--------------------------------------------
timeseq0.t 1440134670777
stored to arrray 1440134670777
t0 1440134670277
tt 1440134671278
t0 1440134670277
tt 1440134672277
-------------------------------------------
{ c: 7 }
{ e: 210 }
atomic { a: 1, b: 2, c: 7, d: 200, e: 210 }
{ d: 200 }
{ b: 2 }
{ a: 1 }
--------------------------------------------
{ c: 35 }
{ e: 1050 }
atomic { a: 5, b: 10, c: 35, d: 1000, e: 1050 }
{ d: 1000 }
{ b: 10 }
{ a: 5 }
--------------------------------------------
{ m: 'some' }
{ n: 'time' }
{ p: 'Promised' }
{ o: 'other' }
{ m: 'some' }
{ n: 'time' }
{ p: 'Promised' }
{ o: 'other' }
--------------------------------------------
Any Event Function can be wrapped.
--------------------------------------------
1.002
2.004
3.006
4.007
5.008

React Physics Test

enter image description here


index.jsx

/*global React __ */

(() => {
  'use strict';
  //MKS system of units
  var V0 = 85.0; // m/s
  var DEG = 30; //degree
  var THETA = DEG / 180 * Math.PI; //radian
  var G = 9.8; //gravity const

  //10msec time resolution
  //t seconds elapsed since t0
  var t = __.intervalSeq(10).tMap((tt, t0) => (tt - t0) / 1000);

  var x = t.tMap((t) => V0 * Math.cos(THETA) * t);

  var y = t.tMap((t) => V0 * Math.sin(THETA) * t - 1/2 * G * Math.pow(t, 2));

  //==============================================================
  var Drawscale = 4; //4 dot = 1 meter

  class ReactComponent extends React.Component {

    constructor() {
      super();
      var timeseq = __([x, y])
        .tMap(([x, y]) => [50 + x * Drawscale, 300 - y * Drawscale])
        .tMap(([x, y]) => {
          this.rx = x;
          this.ry = y;
          this.forceUpdate();
        });
    }

    render() {
      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.rx}
      cy = {this.ry}/>
    </svg>
  </div>
      );
      return el;
    };
  }

  var mount = React.render(<ReactComponent/>, document.body);

})();

Live Demo

http://sakurafunctional.github.io/demo/react-physics/

2015年8月3日月曜日

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

【注意】この記事は2015年夏に書かれましたが、事態は極めて流動的であり、この記事の内容はすぐに古くなる可能性があります。

JavaScriptはES6+からのトランスパイル形式が標準になりつつある

これまで、CoffeeScriptやTypeeScriptなどJavaScriptトランスパイル言語がありましたが、標準ではありませんでした。

しかし、FacebookのReactの独自言語JSXや次世代JavaSciptのECMA Sciptバージョン6(ES6/コードネームHarmony)が台頭してくるにつれ、すべてはES6+からレガシーのバニラJavaScript(ES5以下)へ、トランスパイルする形式に統合されつつあります。

Reactのビルドシステムは、トランスパイラBabel(旧6to5)へ移行、JSTransformerなどは廃止の方向

Deprecating JSTransform and react-tools (June 12, 2015)

Today we’re announcing the deprecation of react-tools and JSTransform.

As many people have noticed already, React and React Native have both switched their respective build systems to make use of Babel. This replaced JSTransform, the source transformation tool that we wrote at Facebook. JSTransform has been really good for us over the past several years, however as the JavaScript language continues to evolve, the architecture we used has begun to show its age. We’ve faced maintenance issues and lagged behind implementing new language features. Last year, Babel (previously 6to5) exploded onto the scene, implementing new features at an amazing pace. Since then it has evolved a solid plugin API, and implemented some of our non-standard language features (JSX and Flow type annotations).

react-tools has always been a very thin wrapper around JSTransform. It has served as a great tool for the community to get up and running, but at this point we’re ready to let it go. We won’t ship a new version for v0.14.

Migrating to Babel

Many people in the React and broader JavaScript community have already adopted Babel. It has integrations with a number of tools. Depending on your tool, you’ll want to read up on the instructions.

We’ve been working with the Babel team as we started making use of it and we’re confident that it will be the right tool to use with React.

enter image description here

https://app.codegrid.net/entry/babel-1

次世代デファクト、Facebook-ReactのJSXとES6トランスパイラBabelの親密な関係

上記Facebookのブログで発表されたBabelへビルドシステムを完全移行させる方針、そして、FacebookのReact開発チームがBabel開発チームと協働していることから明らかですが、ES6+トランスパイラであるBabelはJSXを完全にサポートしており、今後React-JSXの「標準」のコンパイラとなります。

ES6へ移行する最大の問題は、巷のブラウザ、そしてnode/io.jsに何時まで経ってもまともにサポートされておらず、実用的な観点から実入りがないというものがありましたが、BabelによってES5以下にトランスパイルされるため、互換性の問題は無くなり、今すぐすべてのES6仕様が利用できることになります。

そして、JSXは今後、ES6+の仕様に準拠し、依存する言語仕様に進化していく方針なので、Babelに適応することで、すべての問題が解決されます。今後JavaScriptのプログラマはBabelのトランスパイルシステムにコーディングを依存していくことになります。

ATOMエディタではどうなのか?

Built-in 6to5 support

Since this post was originally published the 6to5 library was renamed to babel so packages should now use the “use babel”; pragma in their JavaScript files.

ATOMエディタでは、すでにuse babelと指定することによりBabelがBuilt-inされておりES6でのパッケージ開発のサポートがされています。

念の為ですが、これはパッケージ開発のみのようです。つまり、ATOMにはBabelがビルトインされており、ES6+で開発したATOMライブラリはuse babelフラグの指定により、Babel経由でトランスパイル実行されるということなのでしょう。

ATOMエディタですべてのES6開発をシームレスに行うための最速環境構築

そこで、この記事では、ATOMエディタですべてのES6開発をシームレスに行うための最速環境構築を紹介します。

冒頭に書いたとおり事態は流動的なので、パッケージの組み合わせなどより良いものが近い将来登場する可能性は大いにありますが、現時点で筆者が認識しているベストプラクティスです。

再現性を確保したいので、開発環境をゼロからインストールをすることを想定しています。

ちなみに筆者の環境は、Debian8.1です。

基盤

nvm をインストール

https://github.com/creationix/nvm

nvmからio.jsをインストール

nvm install iojs

. ~/.nvm/nvm.sh
nvm use iojs

確認
node -v

ATOMをインストール

https://atom.io/

Terminalの作業

Babelをnpmインストール

http://babeljs.io/

Babel is a JavaScript compiler.
Use next generation JavaScript, today.

..

npm install -g babel

これで、babelコマンドが利用できるようになり、ターミナルで

babel script.js

などとすることにより、ES6やJSXコードをES5にトランスパイルします。

ESLint with babel-eslintをnpmインストール

http://eslint.org/

The pluggable linting utility for JavaScript and JSX

https://github.com/babel/babel-eslint

babel-eslint allows you to lint ALL valid Babel code with the fantastic ESLint.

Babelプロジェクト公式のESLintプラグインです。ちなみに、JSHintやJSLint用プラグインはプロジェクトには存在しません。時代の流れを感じます。
時代はESLint。JSLintでもJSHintでもなくESLint。

babel-eslintのgithubレポページの説明に従って両方インストールします。

npm install -g eslint babel-eslint

.eslintrcというESLint設定ファイルに以下の内容をコピペし、ホームディレクトリ直下に新規作成します。

{
  "parser": "babel-eslint",
  "env": {
        "es6": true,
        "node": true,
        "browser": true
  },
  "rules": {
   "semi": [2, "always"],
   "strict": 1,
   "no-undef" : 2
  }
}

これでターミナルから

eslint test.jsx

など、ES6やJSXコードをLintできます。

この.eslintrc設定は"rules":{}がほぼ空の最低限の設定
(Strictモードの宣言がないとWarning【レベル1】される、セミコロン必須、定義なしエラー【レベル2】)で、
http://eslint.org/docs/rules/

を参照しながら、ルールを追加し磨き上げていきます。

.zshrcなどに追加しておくと便利なエイリアス

alias a="atom ./"

など。
aでターミナルのカレントディレクトリをATOMで開く。
基本、もともとATOMはGUIのファイラー経由でなくターミナルでプロジェクトディレクトリを開くように設計されていると思う。

ATOMを起動

★Look&Feel

好みで設定。

筆者の場合
Settings > Themes

UI Theme

  • Atom Dark
    (デフォルトのOne Darkはタブが見難すぎる)

Syntax Theme

file-iconsパッケージをATOMにインストール

https://github.com/DanBrooker/file-icons

enter image description here

本体にマージすべき必須パッケージ。

minimapパッケージをATOMにインストール

https://atom.io/packages/minimap

本体にマージすべき必須パッケージ。

language-babelパッケージをATOMにインストール

https://atom.io/packages/language-babel

Language grammar for ES2015 Javascript and Facebook React JSX syntax. The color of syntax is determined by the theme in use.

.js,.babel,jsx es6エクステンションのES6やJSXコードのシンタックスのハイライトをしてくれる。これ自体もLint機能が有るが弱い。

本体にマージすべき必須パッケージ。

ここまでで、表示は整いました。
enter image description here

ここから、上記TerminalプログラムをATOMで利用するためのパッケージをインストールします。

★Lint設定

linter & linter-eslintパッケージをATOMにインストール

linter-eslintの設定

  • Global Node Pathに、npm config get prefix で得られるNodeのグローバル・パスをコピペ。

  • Use Global Lintをチェック。

★コードFormat (Beautify)

esformatterパッケージをATOMにインストール

Format On Saveにチェック。

JSXのコードで、
class ReactComponent extends React . Component {
のところだけ、余分なスペースが入るのが気になるが、Lintと実行は問題ない。`

~/.atom/packages/esformatter/.esformatter

esformatter-collapse-objectsプラグイン参照を追加

{
"plugins": [
    "esformatter-jsx",
    "esformatter-collapse-objects"
  ],

確認

最終的に6パッケージがインストールされています。

enter image description here

再起動

ATOMのパッケージ、設定は再起動されないと反映されないものがあるので、再起動して挙動を確認します。

オンタイム・トランスパイルメインの設定

一つのやり方として、ファイルエクステンションをJSXあるいはES6に統一しておく、という方法があるでしょう。

node/io.js

標準のnodeコマンドで、

node app.js

と実行する代わりに、Babelに付属しているbabel-nodeコマンドで、

babel-node app.jsx

と直接オンタイムで実行できます。
https://babeljs.io/docs/usage/cli/

トランスパイルのオーバーヘッドがあるだけで、パフォーマンスのデメリットはありません。

Browser

開発時には、オンタイムでトランスパイルしたほうが便利です。
React-JSXでは、JSX-Transfomerというオンタイムのトランスパイラーが利用できますが、これも廃止の方向に向かっており、同様に、Babelを利用します。

https://babeljs.io/docs/usage/browser/

ドキュメントにあるとおり、

<body>
<script src="node_modules/babel-core/browser.js"></script>

<script type="text/babel">
//your Babel ES6/JSX code
</script>
</body>

とするのですが、一部ES7の機能を使いたい場合などのオプション指定のやり方はわからなかったので、同じページにあるAPIを利用して以下のようにも書けば、{state: 0}などのオプション設定が可能になります。

<body>
  <script src="./babel-browser.js" ></script>
  <script>
   var urls = ["./index.jsx"];
    xhrDoc = new XMLHttpRequest();
    xhrDoc.open('GET', urls[0])
    if (xhrDoc.overrideMimeType)
        xhrDoc.overrideMimeType('text/plain; charset=x-user-defined')
    xhrDoc.onreadystatechange = function() {
        if (this.readyState == 4) {
            if (this.status == 200) {
                var data = this.response; //Here is a string of the text data
                var out = babel.run(data, { stage: 0 });
            }
        }
    }
    xhrDoc.send() //sending the request
  </script>
</body>

プロダクション

開発でないプロダクションでは、特にブラウザではES6+/JSXからES5以下へ、あらかじめオフライン環境でトランスパイルしておいたほうがパフォーマンス的に推奨されます。

この場合は、ターミナルで普通にbabelコマンドでES6+/JSXファイルをトランスパイルする、ということになります。

前回、前々回の記事

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

JavaScriptで時間発展する物理系=私達が生活するこの宇宙の挙動を、関数型プログラミングでイミュータブルに記述する、という関数型リアクティブプログラミング(FRP)の概念実証

はこのBabelを用いたES6+/JSXのコードで開発しています。

2015年7月31日金曜日

JavaScriptで時間発展する物理系=私達が生活するこの宇宙の挙動を、関数型プログラミングでイミュータブルに記述する、という関数型リアクティブプログラミング(FRP)の概念実証

時間発展する物理系、つまり、私達が生活するこの宇宙の挙動を、関数型プログラミングでイミュータブルに記述する、という関数型リアクティブプログラミング(FRP)の概念実証をJavaScript言語でしてみましょう。

我々の馴染みの深い「放物線」を例に取ります。
「放物線を描く」と日常的によく使いますが、物理学(日本語)では正確には、「斜方投射」と言います。

斜方投射(しゃほうとうしゃ)とは物体をある初速度をもって空中に投げ出す動作である。空気抵抗が十分小さく無視できる場合、斜方投射された物体の軌跡は放物線を描く

enter image description here

水平方向に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);
//============================================================== 
//=========================================================================== 
});


Live Demo

http://sakurafunctional.github.io/demo/react-physics/

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

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

『関数型プログラミングに目覚めた!』のレビュー(Day-1)のコメント欄で計算機科学の基礎としての、プログラミングの「時間」要素、そして「時間」を考えるとは即ち、物理学を考えることである、という重要な論点が確認されています。

JavaScriptのDate.now()をimmutableなストリームと、透過な参照をする関数として考えるとき、誤解されやすいのが、

参照透過性(さんしょうとうかせい、英: Referential transparency)は、計算機言語の概念の一種で、文脈によらず式の値はその構成要素(例えば変数や関数)によってのみ定まるということを言う。 具体的には変数の値は最初に定義した値と常に同じであり、関数は同じ変数を引数として与えられれば同じ値を返すということになる。 当然変数に値を割り当てなおす演算である代入 (Assignment) を行う式は存在しない。 このように参照透過性が成り立っている場合、ある式の値、例えば関数値、変数値についてどこに記憶されている値を参照しているかということは考慮する必要がない、即ち参照について透過的であるといえる。

のうち「文脈によらず」「関数は同じ変数を引数として与えられれば同じ値を返す」という要素だと思います。
@nonstarter氏が感じる「謎」

t1 = Date.now(); (0〜9まで足してコンソールに表示); t2 = Date.now(); console.log(t1 == t2);

t1 = Date.now(); (0〜9まで足してコンソールに表示); t2 = t1; console.log(t1 == t2);
とで結果が異なる、というDate.now()の単純明瞭この上ない「参照不透明性」をどうするつもりなのかはまったく謎のママなわけです。

はまさにこの要素の疑念だと読み解けます。

まず、コメント欄で誰も注意していないので、厳しく注意しておきますと、この@nonstarter氏によるコードは関数型プログラミング、あるいは宣言型プログラミングのコードでもなんでもありません。

関数型・宣言型でない理由は単純で、

t1 = Date.now(); // ① 
<09まで足してコンソールに表示するための処理コード> ; // ②
t2 = Date.now(); // ③

はコードが
ステップ ①
ステップ ②
ステップ ③
というように、上から下へ時間遷移とともに流れ、値はコードの上下関係、時間の前後に依存する、という命令型の発想を前提として書かれている命令型のコードなので、そもそもが「参照不透明性」だとか関数型のコードとしては議論するのは間違いです。
ステップ ①

ステップ ③
では「時間」が違うので、Dateというストリームに参照透明にアクセスする時間関数now()の返り値は異なって当然です。

正しい関数型・宣言型のコードを書くと、

var f = function() {
  console.log(Date.now());
};
var dummy1 = setTimeout(f, 0); //ユーザがコードを実行した瞬間に即時実行
var dummy2 = setTimeout(f, 1000); //ユーザがコードを実行した1秒後に実行

こうなります。コードのロジックがコードの上下関係や、時間の前後関係にまったく依存していないことに注意してください。この「非同期」で宣言型のコードでは、ステップ①②③などありません。

<0〜9まで足してコンソールに表示するための処理コード> ;
を関数型で書くならば、その処理の終了のコールバック関数で書きます。@nonstarter氏が書いたような命令の終了の「同期」を待つような命令型のコードで書いてはいけません。

now()の実引数が空だから、「関数は同じ変数を引数として与えられれば同じ値を返す」事を考えるとおかしい!と思うのも、すでにコメント欄で反論されているとおり、間違った考えです。
now()というのは、その特性を表す字面でも明確ですが、時間関数であって、 値はユーザの現在時間に依存するのです。
数学的には、概念的には、コードに表記されずとも暗黙に、ユーザの現在時間が実引数として渡される関数です。

now()という時間関数が返す値はユーザの現在時間に依存するというのは、

@chimetorch氏が引用したコード
http://www.w3schools.com/jsref/tryit.asp?filename=tryjsref_onmousemove_dom

document.getElementById("myDIV").onmousemove = function() {myFunction(event)};

function myFunction(e) {
    var x = e.clientX;
    var y = e.clientY;
    var coor = "Coordinates: (" + x + "," + y + ")";
    document.getElementById("demo").innerHTML = coor;
}

event値はユーザの現在時間に依存するというのと等価ですし、

elmのコード

import Graphics.Element exposing (..)
import Mouse
main : Signal Element
main = Signal.map show countClick
countClick : Signal Int
countClick = Signal.foldp (\clk count -> count + 1) 0 Mouse.clicks

の「シグナル」のインデックス値はユーザの現在時間に依存するのと等価です。

もちろん、上記elmの「シグナル」同様に、JavaScriptのDateストリームをFRP的に拡張して、

var f = function(now){console.log(now);};
var dummy = Date
            .interval(1000) // specifies a 1sec interval between each element
            .map(f);

と書けるようにするのは、大変意義あるハックですが、標準で、

var f = function(){console.log(Date.now());};
var dummy = setInterval(f, 1000);

書くほうが楽です。

私が書いた、worldcomponentも、実用的な観点から、
Date.now()と同様に、now()関数で直接値が参照できるように設計しています。これまで触った数々のFRPライブラリの経験から、この仕様のほうが取り回ししやすいという結論です。

もしくは、

var main = Date.map((now) => {
  //now はユーザの現在時刻
  //ここにすべてのコードを記述していく
});

と暗黙でなく明示的な表記にすれば、関数型のコードとしてより美しいかもしれません。
しかし、これはただ
明示的な構造の中にnowと書くか、
暗黙的な実引数でDate.now()と書くかの違いにすぎません。

いずれにせよ、@nonstarter氏による命令型のコード以外、私が書いたものも含め上記すべての関数型・宣言型のコードは、

  • コードのロジックがコードの上下関係や、時間の前後関係にまったく依存していない

のですが、

  • コードの中の値はユーザの現在時間に依存する

ことに注意してください。

前者と後者の区別がつくプログラマは、関数型プログラミング、計算機科学のほんとうの基礎の素養がきちんとありますが、前者と後者の区別がつかず、関数型でなく命令型のコードを書きながら『単純明瞭この上ない「参照不透明性」』などと発言してしまう人は勉強しなおしたほうがよろしいでしょう。

前者については、命令型でない関数型の基礎なので、特にいまさら説明を加える必要はないと思います。 

後者については、関数型プログラミングで、時間変化する領域に踏み込むことになるので、多少の説明が必要だと思います。

念の為、もう何度も繰り返しているのですが、この部分を説明していのが、
私の著書
関数型プログラミングに目覚めた! IQ145の女子高生の先輩から受けた特訓5日間
やSICP
99%のプログラマがIQ145のJKに「ダサい」と言われてしまう理由とは?【その1】「計算機科学のほんとうの基礎」を理解していない。IQ145のJKと同じ事を語るMITの権威とSICPという聖典の権威を借りてマインドコントロールを解いてみよう
であるということです。

(後者) コードの中の値はユーザの現在時間に依存する、つまり、関数型プログラミングと古典物理学の密接な関係について解説します。

まず、根本の根本の部分ですが、このように時間の値そのものを取り扱うコードにしても、イベント(シグナル)を使うマウスポインタ、クリックのコードにしても、値は時間変化します。

  • コードの中の値はユーザの現在時間に依存する

時間変化するから、「文脈によって変わる」、だから「参照不透明」なミュータブルと考えるのは間違いです。

  • コードのロジックがコードの上下関係や、時間の前後関係にまったく依存していない

というのが、「文脈によって変わらない」という意味で、「参照透明」であるということです。

私、そしてSICPの著者が関数型プログラミング、計算機科学の基礎と不可分として使う物理学の用語では、時間発展と言うのですが、

時間発展(じかんはってん)とは、時間が進むことで物理系が変化することである。
古典物理学における時間発展とは、物理量の値が時間によって変化することである。

変化しているのは、時間が進むことで変化する我々の世界の「物理系」「物理量」であることを理解してください。

古典物理学にせよ、関数型プログラミングのコードにせよ、それは数学なので、「参照不透明」に値が変化することなどはありえません。

古典物理学で絶対時間tが時間が進む(様に見えている)ことで物理系が変化し、物理量の値が時間発展するからといって、絶対時間tが破壊的代入されている、わけではありませんし、関数型プログラミングにしても全く同様です。

正しい関数型・宣言型のコード

var f = function() {
  console.log(Date.now());
};
var dummy1 = setTimeout(f, 0); //ユーザがコードを実行した瞬間に即時実行
var dummy2 = setTimeout(f, 1000); //ユーザがコードを実行した1秒後に実行

は、時間が進むことで変化する我々の世界という「物理系」において不変(immutable)で、参照透過です。

Popular Posts