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年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のコードで開発しています。

Popular Posts