ushumpei’s blog

生活で気になったことを随時調べて書いていきます。

browser-syncでブラウザ自動更新

Node.jsでコードを書いていると、ターミナルとブラウザの行き来が頻発して面倒です。自分のノートPCはモニタが小さいので、ウィンドウを切り替えていると埋もれてしまい、それを探すために集中力が切れてしまったりします。

browser-syncを使ってコードを書き換えるとブラウザが自動更新されるようにしてみました。expressと連携することもできるので、そのこともメモしておきます。

単純な使い方

npm install --save-dev browser-sync

監視対象のファイルを指定して起動します。

./node_modules/.bin/browser-sync start --server --files index.html 

コマンドを実行するとlocalhost:3000でサーバが起動します。ブラウザが立ち上がり、Connected to Browser Syncという文字がページ右上に表示されます。この状態で、index.htmlを編集するとブラウザが自動更新されます。


try browser sync

expressと連携

expressでサーバを立てている場合、connect-browser-syncミドルウェアを利用してサーバに自動更新の機能を組み込むことができます。まずはインストールします。

npm install express --save
npm install browser-sync --save-dev
npm install connect-browser-sync --save-dev

app.jsを作成します。

var express = require('express');
var app = express();

if ( app.get('env') === 'development' ) {
  var browserSync = require('browser-sync');
  var connectBrowserSync = require('connect-browser-sync');

  var browserSyncConfigurations = { "files": "static/*" };
  app.use(connectBrowserSync(browserSync(browserSyncConfigurations)));
}

app.use(express.static(__dirname + '/static'));

app.get('/', function (req, res) {
  res.sendFile(__dirname + '/static/index.html');
});

app.use(function(err, req, res, next) {
  console.error(err.stack);
  res.status(500).send('Something broke!');
});

app.listen(3000);

ifの部分がbrowserSyncの設定です。オプションをオブジェクトでbrowserSync関数に渡し、connectBrowserSyncミドルウェアをexpressに登録しています。オプションのfilesは監視対象のファイルを設定します。ワイルドカードで指定したり、配列として複数のパスを渡すこともできます。ここではstatic以下のファイルをすべて監視しています。ここをコンパイル後のjsの吐き出し先に設定したりすれば、webpackと協調して使うこともできますね。 ミドルウェアの登録のタイミング次第では動かなかったりして少しはまりました。静的コンテンツのディレクトリ設定をbrowserSyncの前に設定したら監視が始まりませんでした。

感想

browserSyncで検索すると大体はgulpと一緒に使おうみたいな記事が見つかります。設定ファイルの記述方法を覚えるのが大変なので、gulpはやらなくていいかなと思い、自動更新に絞った使い方を調べました。

上記二つのケースどちらでも、browserSyncを起動すると管理サーバも立ち上がるのですが、その使い方があまりわかっていません。また「snipetを貼り付けてね」みたいなことをbrowserSyncから注意されるのですが、これが何に使われているかわからないです。自動更新できているから、ひとまず放置しています。

追記: ブラウザ同士のイベントを同期することもできるみたいです。同一ネットワーク内だと同期されるのかな?

圏, 関手, 自然変換

圏論の定義メモ

Def.圏(category)

 C は次のデータからなります;

  • 対象(objects)
    •  A,  B,  C...
  • 射(arrows)
    •  f,  g,  h...
  • ドメイン(domain), コドメイン(codomain)
    • 任意の射  f に対し, 対象  dom(f),  cod(f) が定まる. この時  f : A \rightarrow B と表す. (ただし  A = dom(f) B = cod(f)
  • 合成(composite)
    • 任意の射  f : A \rightarrow B g: B \rightarrow Cに対し、 h = f \circ g: A \rightarrow C という射が定まる.
  • 恒等射(identity arrow)
    • 任意の対象  A に対し,  1_A という射が定まる.

これらのデータは次の法則を満たします;

  • 結合律(associativity):
    • 任意の射  f,  g,  h cod(f) = dom(g),  cod(g) = dom(h)を満たすものに対し,  h \circ (g \circ f) = (h \circ g ) \circ f が成り立つ.
  • 恒等律(unit):
    • 任意の射  f: A \rightarrow B に対し,  f \circ 1_A = f = 1_B \circ f

Def.関手(functor)

 C,  D に対し, 関手  F : C \rightarrow D とは, 圏  C の対象を圏  D の対象に, 圏  C の射を圏  D の射に写すもので, 次を満たします;

  •  F(f : A \rightarrow B) = F(f) : F(A) \rightarrow F(B)
  •  F(1_A) = 1_F(A)
  •  F(g \circ f) = F(g) \circ F(f)

Def.自然変換(natural transformation)

 C,  D , 関手  F, G : C \rightarrow D に対し, 自然変換  \eta : F \rightarrow G とは, 圏  C の任意の対象  A に対し, 圏  D の射  \eta_A: F(A) \rightarrow G(A) を与えるもので, 次を満たします;

  •  C の任意の射  f: C \rightarrow \acute{C} に対し,  \eta_{\acute{C}} \circ F(f) = G(f) \circ \eta_C が成り立つ.

感想

だからどうしたという感じですよね。写像だ、とか集合だ、とか限定すると間違ってしまうためぼんやりした定義になってしまいます。はてなの所為なのか可換図式書けませんでした...

PCのカメラを起動する

WebRTCで遊んでみたいので、手始めにPCの内臓カメラを起動するだけのページを作成します。

navigatorオブジェクトのgetUserMediaメソッドを使用することでデバイスにアクセスできるみたいです。ただ、ブラウザ環境ごとにこのメソッドがあったりなかったりするため、代替となる関数を列挙してそのうちあったものを使用する、というコードを書きます。

navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || window.navigator.mozGetUserMedia || navigator.msGetUserMedia;

メソッド自体はこんな形をしています。

navigator.getUserMedia(constraints,successCallback,errorCallback)

次にこのAPIを使用してメディアに接続します。

    navigator.getUserMedia({video: true, audio: true},
    stream => {
      video.src = window.URL.createObjectURL(stream);
    },
    error => {
      console.error(error);
      return;
    });

あとは適当にhtmlをかいた、ら動くと思ったのですが、エラーも吐かずになぜか動かない。

そういえばwebサーバに置かないとダメ、みたいなことを聞いた気がしたので、nodeでexpressを使ってサーバを立てました。

mkdir webrtc
cd webrtc
npm init -y
npm install express

二つのファイルを作成します。

server.js

var express = require('express');
var app = express();

app.get('/', function (req, res) {
  res.sendFile(__dirname + '/index.html');
});

app.use(function(err, req, res, next) {
  console.error(err.stack);
  res.status(500).send('Something broke!');
});

app.listen(3000);

index.html

<html>
  <head>
    <title>sample</title>
  </head>
  <body>
  <video id='video' autoplay></video>
  <script type="text/javascript">
    let video = document.querySelector('video');
    navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;

    navigator.getUserMedia({video: true, audio: true},
    stream => {
      video.src = window.URL.createObjectURL(stream);
    },
    error => {
      console.error(error);
      return;
    });
  </script>
  </body>
</html>

あとは起動してlocalhostの3000ポートにアクセスします。

node server.js

f:id:ushumpei:20160717043812p:plain

なんか暗いですが映りました!

感想

getUserMediaがPromise化対応したそうですが、chromeはダメみたいです。

近々reduxコンポーネントとして、動画の録画、再生、停止、保存機能を持った部品を作成したいです。

あと通信部分で、同一LAN内の携帯とPCとかならビデオチャットできないだろうか?と考えています。

オーダー

オーダーについて。適当に済ましていたので、おぼえがきします。アルゴリズムでも数学でも見ることがよくありますが、若干うろ覚えです。

定義

 { f(x) } { x \rightarrow \infty }のときオーダー { O(g(x)) }である。

 { :\Longleftrightarrow }

 {}^\exists x_{0}, {}^\exists M > 0 \quad s.t. \quad {}^\forall x > x_{0} \Longrightarrow \vert f(x) \vert \lt M \vert g(x) \vert

これを変形すると、 { \lim_{ x \rightarrow \infty } \left\vert \frac{ f(x) }{ g(x) } \right\vert \lt \infty } となることから、この定義は  { f(x) } { g(x) } より発散する速度が遅いということを意味しているのがわかります。この時  f(x) g(x) で抑えられる、と言ったりするようです。

これに対し似た記法で、 f(x) = o(g(x)) \quad x \rightarrow \inftyというものもあります。この時、以下が成り立ちます。

 { \lim_{ x \rightarrow \infty } \left\vert \frac{ f(x) }{ g(x) } \right\vert = 0 }

詳細な定義は省略しますが極限が0になることが違います。  f(x) g(x)より発散する速度が、 O(g(x)) の時より、十分遅いというイメージです。この時  f(x) g(x) に比べ無視できる、と言ったりするようです。例えば、写像  { f : { \mathbf R }^n \longrightarrow { \mathbf R }^m } {\bf x } = {\bf a } で全微分可能とは、

 { {}^\exists A : n \times m \, matrix \quad s.t. \quad f({\bf a} + {\bf h}) = f({\bf a}) + A {\bf h} + o(\vert\vert {\bf h} \vert\vert) }

です。ここでは  {\bf h} \rightarrow 0 となっていて多少変化がありますが基本的に意味は変わっていません。つまり、 f({\bf a} + {\bf h}) f({\bf a}) + A {\bf h} {\bf h} のノルムが十分小さいところでは限りなく等しいということが言えます。

アルゴリズムなどではよく、 O(n) O(\sqrt{n}) などと言ったりしますね。これらは「入力データ量  n に対する実行時間は  O(n)」みたいな文脈だったと思います。これはつまり、

  \lim_{ n \rightarrow \infty } \left\vert \frac{ \text{ アルゴリズムの実行時間 } }{  (n: \text{入力データ量} ) } \right\vert = const \lt \infty

より、

 \text{ アルゴリズムの実行時間 } =  const \times (n: \text{入力データ量})

この場合はアルゴリズムの実行時間が  n に比例する、ということですね。 n^2 なども同様です。

感想

わかったようなわかってないような微妙な気分です。当たり前のことを言っている気持ちにもなりました。

まあ少なくとも毎回ググらなくてよくなっただけ、進歩かと思います。

javascriptで実行時間を表示する

短いメモです。

console.timeconsole.timeEndを使うとスクリプトの実行時間を表示することができます。

var loop = n => {
  console.time('timer');
  for(i = 1; i <= n; i++) {
    for(j = 1; j <= n; j++) {
      console.log(`${i} x ${j} = ${i*j}`);
    }
  }
  console.timeEnd('timer');
}

引数で与えている文字列を使って、スタートとエンドを対応させます。

ここを参考にしました[JavaScript]使い分けるだけで今すぐデバッグ効率を上げる、consoleオブジェクトの関数 - Qiitaconsoleオブジェクトの関数がたくさん書かれています。

ReduxとExpressかElectronか

Reduxのチュートリアルを見終わったので、実際に手を動かしてみようと思い、リポジトリを作成してみました。中身はExample: Todo List | Reduxです。

github.com

expresselectronで動作確認ができます。

感想

写経しているとreduxに関して徐々にわかってきました。reduxは画面状態をStore内のstateオブジェクトとして持っていて、操作によって発行されるactionオブジェクトとstateをセットで、Reducerに渡すことで、新たなstateを取得します。 { \displaystyle  (state, action) \longmapsto state}

今回の登場人物は、

  • Component(presentation, container)
  • Action Creator
  • Reducer & Store

処理の流れもこの順番です。

画面はコンポーネントComponent)のツリー構造で表現されます。コンポーネントにはPresentation ComponentContainer Componentの二種類があり、Presentation Componentは構造を、Container Componentは状態を変化させる方法を定義します。単独で部品としても使えますが、Container Componentで定義した状態を変化させる関数を、react-reduxライブラリに含まれるconnect関数を使って、Presentation Componentに結びつけて使用したりもできます。また、このconnectによってStoreComponentの結びつけも行なっているようです。(ちょっと調べないと、です)
また、コンポーネントのツリーの頂点にProviderというreact-reduxライブラリに含まれるコンポーネントを追加しているので、ここが状態をツリーの枝に伝える仕組みを提供しているのかもしれないです。

特定の動作に対して発行するActionAction Creatorで定義しておきます。これは最低限typeというプロパティを持ったオブジェクトを生成すれば問題ないようです。

ReducerStoreを定めているのだろうという認識で、この二つは同じ行に書いています。(実装的な視点、ですかね)Reducerは古いstateと、発行されたactionを引数に新しいstateを返します。reduxライブラリのcreateStore関数によってReducerからStoreが生成されます。

いろいろ書きましたが、それぞれの部品はわかるものの、連結部分がわかりにくいという感想です。

知らなくてはいけないのはreact-reduxProviderconnectによっていかにコンポーネントStoreを結びつけているか、という部分ですかね。

Reduxの勉強3

前々回

前回

引き続き、Reduxのレッスン動画を視聴した時のメモです。

  • 21: ToDoアプリのリファクタリング。見た目と挙動を分けます。Main container componentからPresentational componentを分離しましょうというはなし。
  • 22: container componentは振る舞いを定義するクラスとして作成した。conponentDidMountconponentWillUnmontメソッドを定義し、presentational componentは状態に対する見た目だけを定義する。のかな?
  • 23: Storeと結びついているコンポーネントforceUpdateする?renderを全体のコンポーネントから分割したコンポーネントに行わせるように修正した。(しかしAddToDoコンポーネントにはrenderがないようだが)厳密にPresentationとContainerを分割する必要はないが、したほうがいいと言ったことを言っている気がする。。。

(だんだんきつくなってきました。。。)

  • 24: StoreにアクセスするコンポーネントがContainerコンポーネントみたいだ。子のContainer ComponentにStoreを渡すために一旦storeをトップレベルの引数として渡す処理を書いた。
  • 25: Providerを使うことでPresentation ComponentからStoreを取り除くことができるみたいだ。ContextによってContainer ComponentにStoreを渡すことができるようになった。Contextを使うにはchildContextTypesを指定しなければいけない。グローバルにアクセスできる感じか。ただしContextはあまり安定していないらしく、がっつり使っているのは良くないとのことです。
  • 26: Providerはライブラリとして取得できるよ、という説明と記述方法でした。
  • 27: ReactReduxライブラリのconnectメソッドを使うことでContainer Componentを作成することができる。最終的にどうなるか知れればいいかなという気分になってきました。
  • 28, 29: connectメソッドを使って色々整理していきます。
  • 30: ActionCreaterについて。

だいぶ聞き取れず、試すこともできず、停滞しています。 後日初めから、アプリを作成しつつ追っかけていこうと思います。。。

webpack、babel、React

Reactの環境構築です。できるだけ覚えることを減らしたいので、webpackbabelreactを軸に必要最低限なものをインストールします。Node.jsの環境が整っている前提です。(npmコマンドが使えればOKかと思います)

それぞれに関するメモです。

  • webpack: jsxとかes6記法で書いたスクリプトとかをクライアント側に送るためにまとめるビルドツールという認識です。モジュール間の依存性を解決しつつビルドしてくれるそうです。チュートリアルやったらわかった気になれました。loaderというモジュールを追加することで、jsファイルだけでなくcssなどのまとめ方も指定できます。
  • babel: es6記法を一般的なブラウザで読めるようにコンパイルするもの。webpackでes6記法を含んだファイルをビルドする際に、エンジンとして使いました。インストールのみで特に何もしていないです。
  • react: jsのテンプレートエンジンです。jsxとして書くのが楽なので書くと、そのままではブラウザで動きません。なのでwebpackで普通のjsファイルにビルドさせます。

設定

パッケージファイルを作成し、必要なパッケージをインストールします。

npm init -y
npm install webpack babel-loader babel-core babel-preset-es2015 babel-preset-react react react-dom --save-dev

次はwebpackの設定です、設定ファイルを記述しない場合webpackにいろいろオプションを指定して実行することになりますので、ファイルwebpack.confing.jsを作成します。

webpack.config.js

module.exports = {
  entry: "./entry.js",
  output: {
    path: __dirname,
    filename: "bundle.js"
  },
  module: {
    loaders: [
      {
        test: /\.(js|jsx)$/,
        exclude: /node_modules/,
        loader: "babel",
        query: {
          presets: ['es2015', 'react']
        }
      }
    ]
  }
};

このファイルにwebpackコマンド実行時の設定をオブジェクトとして記述していきます。プロパティの説明をします。

  • entryがビルドしたいスクリプトになります。この例ではentry.jsと設定しています。内部でrequireとか呼び出ししているファイルは、webpackが勝手にまとめてくれます。
  • outputには出力ファイルのパスと名前を記述します。ディレクトリ構造を考えていないので特にパスは指定してません。
  • moduleloadersという配列に、どのファイルをどのようにビルドするかの設定をオブジェクトで記述します。今回は一つだけです。
    • testにはどのファイルを対象にするかを正規表現で記述します。今回は拡張子がjsまたはjsxのものを対象にします。
    • excludeには除外するもののパターンを記述します。
    • loaderはビルドするエンジンを指定しているのだと思います。
    • loaderに機能を追加するのがpresetなんだろうか。presetsはes6記法とreactに関するものを指定しました。

次に、順番が前後していますが、entry.jsとReactのコンポーネントと動作確認用のindex.htmlを作りましょう。

entry.js

window.onload = () => {
  require('./Hello.jsx');
}

Hello.jsx

const React = require('react');
const { render } = require('react-dom');

const Hello = React.createClass({
  render: function() {
    return (
      <div className="hello">
        Hello, world!
      </div>
    );
  }
});
render(
  <Hello />,
  document.getElementById('root')
);

index.html

<html>
  <head>
    <meta charset="utf-8">
  </head>
  <body>
    <script type="text/javascript" src="bundle.js" charset="utf-8"></script>
    <div id="root"></div>
  </body>
</html>

あとはコマンドを叩くだけです。

./node_modules/.bin/webpack

実行完了したらindex.htmlをブラウザで確認してみてください。Reactっぽさはないですが、レンダリングされているのが確認できると思います。

必須ではないですがコマンドの実行はpackage.jsonscriptsに記述しちゃうと楽です。

package.json

{
  "name": "webpack-tutorial",
  "version": "1.0.0",
  "description": "",
  "main": "bundle.js",
  "dependencies": {
    "webpack": "^1.13.1",
    "css-loader": "^0.23.1",
    "style-loader": "^0.13.1",
    "babel-core": "^6.10.4",
    "babel-loader": "^6.2.4",
    "babel-preset-es2015": "^6.9.0",
    "babel-preset-react": "^6.11.1",
    "react": "^15.2.0",
    "react-dom": "^15.2.0"
  },
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "webpack": "webpack --progress --colors"
  },
  "author": "",
  "license": "ISC"
}

以下で起動できるようになります。

npm run webpack

以上です。コードはgithubに上げました。リポジトリ名がチュートリアルとなっていますが全然チュートリアルではないですが。。。

感想

ビルドツールのノリが少しわかりました。ビルドツールが自分にとって身近ではないのは、頻繁にビルドしないからに尽きるんでしょうね。

ともあれようやくReactが動いたので、Reduxのチュートリアルを試すことができます。

Reduxの勉強2

前回

動画が30分で終わるかと思ったら30回あることに気がついて力尽きてしまったので、今日はその残りを見ていきます。

Webpackを使えるようになろうとか言っていましたが、いまの腰を据えて試せていないので停滞しています。残りの動画を放っておくとちょっと分かった気になっているので見なくなる可能性があります、こちらを優先させていただきます。

  • 11: todos Reducerをテストファーストで書いた。actionにidがふってあるが、どこまでふったか、stateかどこかに数字を控えなければいけないのだろうか?(後の動画でグローバル変数として保持しているのがわかる)
  • 12: todos Reducerに「ADD_TODO」だけではなく「TOGGLE_TODO」メソッド(case?すくなくともメソッドではない)を追加。副作用なくすためにしっかりテスト書かないとダメ。ちょっと性善説で悩む(でもみんな責任感あるし大丈夫かな)。
  • 13: Reducerの分割。stateのリストを受け取るReducerの内部を、単一のstateを受け取るReducerに切り出す。どんどんReducer同士を結合させちゃえてきな英語を喋っていた気がする、この辺りは副作用のない関数であることが不安を取り去ってくれてますね。想定していないtypeのActionに関してはそのままstate返しましょう、という念押し。
  • 14: Reducerの合成だが、ちょっと難しい。todosとは別のvisibilityFilter Reducerを追加し、それらを包含したtodoApp Reducerを作成。todoApp内部で、各Reducerへの振り分けを行なっているみたい。なんかStoreとReducerの関係性が曖昧になってきた。。。ActionをStoreにdispatchした際に、入れ子になったどのstateに対するActionか指定していないが、これは対象としていない方にundefinedが渡るからシカトしてOKということか?なんか違和感。
  • 15: Reducerの合成はcombineReducersを使うと楽と言っている。またes6の記法で定義した変数a, b, cobj = {a,b,c}と書けばオブジェクトのkey valueが勝手に入るらしい。「object literal shorthand anotation」だそうです。
  • 16: combineReducers の実装を書いて説明してくれる。reduceで少し詰まった。多分、foldlとかと同じでいいんですよね。配列の各要素を使って一つのものをどんどん作っていくイメージをしました。
  • 17: Reactを使ってToDoの「ADD_TODO」機能のユーザインタフェースを作った。また、入力から出力までのReduxの(?)ライフサイクルを説明してくれているので、よくわからなくなったらこれを見るといいかも。
  • 18: 「TOGGLE_TODO」機能をUIから使えるようにした。全体的に言えるのはどの関数も、基本的には全てのstateを総なめして一致したら処理を実行する感じみたいだ。
  • 19: 「visibilityFilter」のUIを作成。画面側の機能とReducerは対応していないという当たり前のことに気がつく。filterをかける処理などは通常の関数で実装しているが、もし自分が作った時にその辺間違えそう。画面表示とstateの違いをちゃんと整理しておかないと危険ですね。
  • 20: ToDoアプリのリファクタリング。Reactコンポーネントの分離について。分離の基準がよく理解できない。イベントハンドラのコールバック関数はどちらが持つべきか等。分離の途中で次回。

感想

本当は今日中に30まで見てしまって、手を動かす時間を取りたかったのですが、眠気が襲ってきてしまったのでこれで終了です。

動画の中で、コンポーネント内でinputの値を取得するために、react callback ref apiを使っていた。常識っぽいので知っておきたいです。

あと、markdownのlistはoffsetが効かないため困りました。今日は動画を11から見始めたので、

11. hogehoge
12. hogehoge
...

と書いていたのですが、画面上では

1. hogehoge
2. hogehoge
...

になってしまい、ちょっと面倒さを感じながら*をかませて対応しました。

JavaScript...

ES6から、「Spread operater」というものが追加されました。「...」を記述することで、配列やオブジェクトを展開する事ができる演算子だそうです。 例えば、

var [x, ...xs] = [1,2,3,4,5,6,7,8,9];
console.log(x);
//=> 1
console.log(xs);
//=> [2, 3, 4, 5, 6, 7, 8, 9]

分割代入との合わせ技だと思いますが、このように余った部分を配列で受け取ってくれます。

可変長引数等で使えますね。

サンプルコードを書いてみました。 比較方法が数値しか対応していなくて残念ですが、比較の優先順位を可変長で受け取るソート関数を書いてみました。

function mySort(array, ...properties) {
  if(properties.length <= 0) return array;
  let comp = (a, b) => {
    let res = 0;
    for(i = 0; i < properties.length; i++){
      let property = properties[i];
      if(match = /^-(.*)$/g.exec(property)) property = match[1];
      let sign = (match) ? -1 : 1;
      if(!(property in a)) throw new Error(`There is no property named ${property}`);
      res = sign * (a[property] - b[property]);
      if(res !== 0) break;
    }
    return res;
  }
  return [...array].sort(comp);
}
var objs = [
{id: 0, a:1, b:1, c:1, d:1},
{id: 1, a:1, b:1, c:1, d:2},
{id: 2, a:1, b:1, c:2, d:1},
{id: 3, a:1, b:1, c:2, d:2},
{id: 4, a:1, b:2, c:1, d:1},
{id: 5, a:1, b:2, c:1, d:2},
{id: 6, a:1, b:2, c:2, d:1},
{id: 7, a:1, b:2, c:2, d:2},
{id: 8, a:2, b:1, c:1, d:1},
{id: 9, a:2, b:1, c:1, d:2},
{id:10, a:2, b:1, c:2, d:1},
{id:11, a:2, b:1, c:2, d:2},
{id:12, a:2, b:2, c:1, d:1},
{id:13, a:2, b:2, c:1, d:2},
{id:14, a:2, b:2, c:2, d:1},
{id:15, a:2, b:2, c:2, d:2}
];
console.table( mySort(objs, '-a', 'b','c') );

配列への要素の追加も副作用なく簡単にかけます。

function mutableExclamate(list) {
  list.push('!');
  return list;
}

function immutableExclamate(list) {
  return [...list, '!'];
}

args = ['y','a','y'];
console.log(args);
//=> ["y", "a", "y"]
console.log(mutableExclamate(args));
//=> ["y", "a", "y", "!"]
console.log(args);
//=> ["y", "a", "y", "!"]

args = ['y','a','y'];
console.log(args);
//=> ["y", "a", "y"]
console.log(immutableExclamate(args));
//=> ["y", "a", "y", "!"]
console.log(args);
//=> ["y", "a", "y"]

そんなに想像力が働かないですね。 ただArray.prototypeを触らなければならない場面は減ると思います。

Reduxの勉強

Redux

ここを一通り読めばわかりそうだ!と思って読み始めたら、いきなりプレディクタブルステートコンテナとか言われてよく分かりません。

Redux is a predictable state container for JavaScript apps. Read Me | Redux

ステートは普通に状態でいいのだろうか?あまり知らないため、用語を使っていたらわけわからなくなると思いながら、とりあえず読み進めることにしました。

30分の動画があるためそれを見る。なんか10個くらいあるようです。(間違ってました、後述)

  1. ToDoアプリを用いて、画面の状態が一つのオブジェクト(State Tree)に対応していることの実演。
  2. State Treeはリードオンリーで、操作(type)とデータを持ったオブジェクト(Action)によって変更される。
  3. Pure FunctionとImpure Functionの違い。副作用がないこと(戻り値を返す以外の方法で出力を行わないことかな?)
  4. StateとActionを受け取り新しいStateを返すのがReducer、これはPure Functionになっている。だから同じStateとActionを入れれば同じStateが必ず得られることが保証される。(ちょっと英語怪しくなってきました...)
  5. 数字を増やしたり減らしたりするだけのCounter Reducerを例に、ReducerとTestの説明をしている。expect(...).toEqual(...)って感じで書いている。またReducerの実装上の注意など説明されていた(未定義なtypeのAction、stateのデフォルト値など)
  6. Reduxの導入と、Storeのもつメソッドの説明。ReduxのcreateStoreメソッドによってReducerを引数にStoreというものが作られている。StoreはsubscribeメソッドによってViewの書き換えを行なったり、stateを保持しているようだ。StoreにActionをdispatchメソッドによって食べさせることで保持しているstateが更新されている。こいつは副作用を担っているっぽいです。
  7. createStoreの実装に関する説明。getState、dispatch、subscribeの三つを提供してくれるがこれらが何をしているかを説明してくれた。subscribeがあまりわからない...内部に持つlisteners配列を更新するが、filter処理はなにをしている?
  8. renderにはReactを使おう!その際はコールバックを渡すのがいいよ、という説明。おそらく先ほどのsubscribeのおかげでStoreが変更を反映してくれているんだろうという程度の理解。
  9. テストにdeepFreezeを使ってイミュータブルな処理をちゃんと書こうという話かな?es6の記法(配列listに対して...listを使うことで中身を展開できる)をつかった小粋な書き方とか勉強になりました。
  10. 引き続きテストの話。Object.assignとes6...objectの記法の説明。自分の英語力だと3点リーダの記法がいいように聞こえたんだけどどうなんだ?

いまさら気がついたのですが、この動画30分ではなく30個の動画だったのですね...

30見ていると何も達成感がないのでとりあえずまとめとしてカウンターアプリを作ってみよう。

と思ったのですが、環境構築がうまくいかずに断念。webpackを勉強しないといけない。

感想

ビルドツールになぜか苦手意識があることが判明しました。なぜ嫌なのだろうか?webpackを調べつつ、Redux触っていきたいです、あわよくばElectronでアプリ作りたいです。

javascriptで波括弧を使ってconst値に分割代入

こんにちは。

クロスプラットフォームのデスクトップアプリがhtml、cssjavascriptで作れてしまうフレームワーク「Electron」をちょっと触ってみようと思ったのですが、「Hello, world」する前に気になったことをメモします。 (Electronとはあまり関係ない内容になっています)

疑問

とりあえずElectronの環境を整えました。

mkdir myapp
npm init -y
cd myapp
npm install electron-prebuilt --save-dev

あとは、Quick Start - Electronを参考に進めていきました。

ウィンドウを表示したり、閉じた時の挙動を制御するシステム系の設定をindex.jspackage.jsonmainプロパティで指定したファイル)に記述するのですが、いざコピペしてやろうと思ってサイトの内容を読んでいるといきなり3行目に以下の記述を見かけました。

const electron = require('electron');
// Module to control application life.
const {app} = electron;
...

constは定数定義で、ES6から使えるらしい、ということは知っていたのですが、

この波括弧{app}はなんなんだ?と思いました。

知らないと恥ずかしいのかもしれないので、いろいろ試してみました。

(以下ごちゃごちゃしています。結論はタイトルに書いてあります)

スコープ

とりあえずconstは関係ない、スコープの問題だろうと当たりをつけて以下のコードをchromeのコンソールで実行しました。

{hoge} = {hoge:'hogehoge'};
console.log(hoge);

確かにこれでもhogehogeがコンソールに出力されます。

constがどうとかではなく、左辺に波括弧の中にオブジェクトのプロパティを記述すると、右辺のオブジェクトが持っているプロパティの値を取り出すことができるという動きです。

左辺の波括弧の中のhogeが外側から参照できること、左辺のhogeに右辺の値が入っていることについて考えなければと思い、javascriptのオブジェクトの代入に関して調べてみました。

javascriptにおいてはオブジェクト型の代入は参照渡しになる、ということを聞いてもしかすると、と考え以下のコードを試してみました。

obj1 = {p1:{c:1}};
p1 = obj1.p1;
p1.cc = 2;
console.info(obj1);
console.info(p1);

obj2 = {p2:{c:1}};
var {p2} = obj2;
p2.cc = 2;
console.info(obj2);
console.info(p2);

二種類の方法を試したのですが違いはありませんでした。 もしかすると波括弧で囲えば値渡しになるとか考えたのですが、それは間違っていました。。。

感想

そもそもなんでこう書かれているかを探るために、Electronのドキュメントのgithubリポジトリをみてみました。

この記法に変更された時のプルリクエストを見ると、Destructing assignmentというコミットメッセージを発見しました!

ググってみると次のページが見つかります。

分割代入 - JavaScript | MDN

分割代入、という構文だったんですね、初めて知りました。

今日はここにたどり着くまでで消耗してしましました...

gnuplotとFFTW

勉強のため、gnuplotgnuplot homepage)とc言語のFFTW(Fastest Fourier Transform in the West.)ライブラリの環境を作ってみます。

gnuplot

gnuplotコマンドラインから使えるグラフィックユーティリティです。科学者や学生向けに数学の関数をヴィジュアル化する目的で作られました。

homebrewでインストールします。こちらを参考にしました。(gnuplotをHomebrewからインストールするときの手順

$ brew install gnuplot --with-aquaterm

aquatermはGUIです。gnuplotの出力を表示するために、インストール時点でオプションを追加します。

インストール完了後gnuplotコマンドで対話環境が起動します。まずはaquatermでsin(x)を表示してみましょう。

gnuplot> set terminal aqua
gnuplot> plot sin(x)

f:id:ushumpei:20160604174532p:plain

出力方式、出力先を設定することで、画像ファイルやhtmlのcanvasとして吐き出すことができます。

gnuplot> set terminal png
gnuplot> set output 'sin_x.png'
gnuplot> plot sin(x)

関数をデータとして吐き出したい場合は、

gnuplot> set table "gnuplot.sample"
gnuplot> set yrange [0:1]
gnuplot> set xrange [-5:5]
gnuplot> plot exp(- x * x / 2) / sqrt(2 * pi)
gnuplot> unset table

とすると、gnuplot.sampleファイルに関数の値が書き込まれます。

# Curve 0 of 1, 100 points
# Curve title: "exp(- x * x / 2) / sqrt(2 * pi)"
# x y type
-5  1.48672e-06  i
-4.89899  2.45106e-06  i
-4.79798  3.99989e-06  i
-4.69697  6.46117e-06  i
-4.59596  1.0331e-05  i
-4.49495  1.6351e-05  i
-4.39394  2.56161e-05  i
-4.29293  3.97238e-05  i
-4.19192  6.09759e-05  i
-4.09091  9.26476e-05  i
-3.9899  0.000139341  i
-3.88889  0.00020744  i
-3.78788  0.000305686  i
-3.68687  0.00044589  i
-3.58586  0.000643795  i
-3.48485  0.000920105  i
-3.38384  0.00130165  i
-3.28283  0.00182273  i
-3.18182  0.0025265  i
-3.08081  0.00346644  i
-2.9798  0.00470779  i
-2.87879  0.00632878  i
-2.77778  0.00842153  i
-2.67677  0.0110926  i
-2.57576  0.0144624  i
-2.47475  0.0186646  i
-2.37374  0.0238433  i
-2.27273  0.0301496  i
-2.17172  0.0377369  i
-2.07071  0.0467541  i
-1.9697  0.057338  i
-1.86869  0.069604  i
-1.76768  0.0836362  i
-1.66667  0.0994771  i
-1.56566  0.117117  i
-1.46465  0.136486  i
-1.36364  0.157443  i
-1.26263  0.179775  i
-1.16162  0.20319  i
-1.06061  0.227324  i
-0.959596  0.251742  i
-0.858586  0.275953  i
-0.757576  0.299423  i
-0.656566  0.32159  i
-0.555556  0.341892  i
-0.454545  0.359787  i
-0.353535  0.374774  i
-0.252525  0.386423  i
-0.151515  0.394389  i
-0.0505051  0.398434  i
 0.0505051  0.398434  i
 0.151515  0.394389  i
 0.252525  0.386423  i
 0.353535  0.374774  i
 0.454545  0.359787  i
 0.555556  0.341892  i
 0.656566  0.32159  i
 0.757576  0.299423  i
 0.858586  0.275953  i
 0.959596  0.251742  i
 1.06061  0.227324  i
 1.16162  0.20319  i
 1.26263  0.179775  i
 1.36364  0.157443  i
 1.46465  0.136486  i
 1.56566  0.117117  i
 1.66667  0.0994771  i
 1.76768  0.0836362  i
 1.86869  0.069604  i
 1.9697  0.057338  i
 2.07071  0.0467541  i
 2.17172  0.0377369  i
 2.27273  0.0301496  i
 2.37374  0.0238433  i
 2.47475  0.0186646  i
 2.57576  0.0144624  i
 2.67677  0.0110926  i
 2.77778  0.00842153  i
 2.87879  0.00632878  i
 2.9798  0.00470779  i
 3.08081  0.00346644  i
 3.18182  0.0025265  i
 3.28283  0.00182273  i
 3.38384  0.00130165  i
 3.48485  0.000920105  i
 3.58586  0.000643795  i
 3.68687  0.00044589  i
 3.78788  0.000305686  i
 3.88889  0.00020744  i
 3.9899  0.000139341  i
 4.09091  9.26476e-05  i
 4.19192  6.09759e-05  i
 4.29293  3.97238e-05  i
 4.39394  2.56161e-05  i
 4.49495  1.6351e-05  i
 4.59596  1.0331e-05  i
 4.69697  6.46117e-06  i
 4.79798  3.99989e-06  i
 4.89899  2.45106e-06  i
 5  1.48672e-06  i

ここでは一列目がx軸、二列目がy軸になっています。三列目はちょっと謎...

このデータを使ってグラフを表示するのも簡単にできます。

gnuplot> plot "gnuplot.sample"

f:id:ushumpei:20160616000500p:plain

FFTW

FFTWは離散フーリエ変換を計算するためのc言語のライブラリです。変換する関数は次元、入力サイズ、実数or虚数別が選べます。

$ brew install fftw

FFTWには離散フーリエ変換を扱うための関数や複素数データ型が用意されています。

FFTW does not use a fixed algorithm for computing the transform, but instead it adapts the DFT algorithm to details of the underlying hardware in order to maximize performance.

FFTWでは入力データに対して、毎回決まった変換アルゴリズムを適応するのではなく、最適化した変換アルゴリズムを用いて離散フーリエ変換を行う仕組みになっています。そのため、変換実行前に「プラン」というものを作成します。複素一次元離散フーリエ変換のプランを作成する関数を見てみましょう。

fftw_plan fftw_plan_dft_1d(int n, fftw_complex *in, fftw_complex *out, int sign, unsigned flags);

fftw_plan_dft_1dfftw_planを戻り値にもつ関数です。引数として次のものをとります;

  • int n: データサイズ
  • fftw_complex *in:入力データ配列
  • fftw_complex *out:出力データ配列
  • int signフーリエ変換(-1)、逆フーリエ変換(+1)かの設定。定数が用意されています。
  • unsigned flags:通常はFFTW_ESTIMATEをつかい、サイズが同じ変換を何回もし、初期化コスト(?)を気にしないならばFFTW_MEASUREを使うみたいです。

感想

力が尽きてしまい、フーリエ変換前後のグラフを出力することは断念しました。sinをフーリエ変換して、一本だけ立つことを確認するとか、関数の和がどんどん短形関数に近づいていく様をみるとか、やりたいです。

フーリエ変換の練習(前半)

f:id:ushumpei:20160612004725p:plain

フーリエ変換について知識がないため、ちょっと勉強してみます。証明的なものを載せていますが、考え方を学ぶためのメモなため正確なことを知りたい場合参考書を当たってください。フーリエ変換の雰囲気がわからなくて困っている場合はちょっとは役に立つと思います。(私も同じ状況なので)

フーリエ変換は関数を周波数で分解した表示に変換できるものです。分解の際に現れる各項は連続関数と定数の積ですが、これらの無限の和を考えることで、不連続な関数に関しても分解が得られるということが面白と思いました。通信関係をはじめとして、広い範囲での応用がされています。

元となった理論は、フーリエ級数の研究なのかと思います。フーリエ級数は周期関数に関する表示を与えるものでしたが、フーリエ変換では周期を無限と考えることで、その対象を広げたところが違いです。

考え方の核は、周期を無限と考えることと、関数空間に対して基底による分解を与える感じでしょうか?一部フーリエ級数と変わらないですが。

前提条件としては、微分積分線形代数(基底とかの話)、複素数(というかオイラーの公式)を知っていれば理解できそうです。

離散フーリエ変換など応用の方面でまだまだ研究されているようで2012年には従来の10倍の変換速度を誇るSFFTといったものも発表されたみたいですね。。。

ということで、数学の勉強方法ってどうするんだろう、としばらく悩んだのですが、ああ、証明を考えてみるのが一番理解できるな、と思い出しました。理解のためにまずはフーリエ級数を証明してみます。なので周期関数の空間について考えます。ちゃんとした参考書みないので記号は適当です、うまくいかなかったらすみません。

周期関数

周期  T の関数の空間を  F_{T} := \{\, f \,|\, f(x) = f(x + T) \} と定義します。

内積は、 \displaystyle {
(f * g) = \int_{0}^{T} f(x)g(x) dx
} で定義します。(内積であることは積分の性質からいけるはず)

 F_{T}の基底が、1(定値関数)、 s_{n}(x) = \sin(\frac{2n\pi x}{T}) c_{n}(x) = \cos(\frac{2n\pi x}{T})  (n \in (1, 2, ...)) になることを示せれば、任意の周期関数  f \in F_{T} は、

 {\displaystyle
f(x) = c + \sum_{n=1}^{\infty} ( a_{n}s_{n}(x) +  b_{n}c_{n}(x) )
}

という形で表せることがわかります。

証明

前半

基底であることを示すには、一次独立と生成系であることを言わなければいけません。

まずは一次独立を示すために、それぞれの基底候補が直交していることを示します。

 \displaystyle{
(1 * s_{n}) = \int_{0}^{T} 1 \times \sin(\frac{2n\pi x}{T}) dx \\
= \left[ - \frac{T}{2n\pi} \cos(\frac{2n\pi x}{T}) \right]_{0}^{T} \\
= - \frac{T}{2n\pi} \left[ 1 - 1 \right] = 0
}

より 1 * s_{n} = 0 がわかりました。 1 * c_{n} = 0 も同様です。

次に、 s_{n} * c_{k} s_{n} * s_{k} と、 c_{n} * c_{k} ですが、これはオイラーの公式を使うといけそうです( sin cos の積の公式を忘れてしまいました...)。

以下の等式が成立します。(記述が面倒なので、 \omega := \frac{2 \pi}{T} とします。)

 \displaystyle{
e^{i \omega (n+k) x} = e^{i \omega n x} e^{i \omega k x}\\
= (c_{n}(x) + i s_{n}(x))(c_{k}(x) + i s_{k}(x))\\
= c_{n}(x)c_{k}(x) - s_{n}(x)s_{k}(x)\\
\quad + i (s_{n}(x)c_{k}(x) + s_{k}(x)c_{n}(x))
}

一方、

 \displaystyle{
\int_{0}^{T} e^{ i \omega (n + k) x } dx\\
= \int_{0}^{T} c_{n + k}(x) + i s_{n + k}(x) dx\\
= \frac{1}{\omega (n + k)}\left[ s_{n + k}(x) \right]_{0}^{T} + \frac{-i}{\omega (n + k)}\left[ c_{n + k}(x) \right]_{0}^{T}\\
= 0
}

なので、

 \displaystyle{
\int_{0}^{T} c_{n}(x)c_{k}(x) dx = \int_{0}^{T} s_{n}(x)s_{k}(x) dx\\
\int_{0}^{T} s_{n}(x)c_{k}(x) dx = - \int_{0}^{T} s_{k}(x)c_{n}(x) dx\\
}

が成り立ちます。さらに kの符号を変えた、  e^{ i \omega (n - k) x } から、

 \displaystyle{
\int_{0}^{T} c_{n}(x)c_{k}(x) dx + \int_{0}^{T} s_{n}(x)s_{k}(x) dx = 0 \, or \,T (n = k)\\
\int_{0}^{T} s_{n}(x)c_{k}(x) dx - \int_{0}^{T} s_{k}(x)c_{n}(x) dx = 0 \quad
}

よってこれを使うと、

 {\displaystyle s_{n} * c_{k} = \int_{0}^{T} s_{n}(x)c_{k}(x) dx = 0 }

 {\displaystyle s_{n} * s_{n} = \int_{0}^{T} s_{n}(x)s_{n}(x) dx = \frac{T}{2} }

 {\displaystyle s_{n} * s_{k} = \int_{0}^{T} s_{n}(x)s_{k}(x) dx = 0 }

 {\displaystyle c_{n} * c_{n} = \int_{0}^{T} c_{n}(x)c_{n}(x) dx = \frac{T}{2} }

 {\displaystyle c_{n} * c_{k} = \int_{0}^{T} c_{n}(x)c_{k}(x) dx = 0 }

つまり、 1 s_{n}(x) c_{n}(x) は直行することがわかります。

以上のことから、

 \displaystyle{
c + \sum_{n=1}^{\infty} ( a_{n}s_{n}(x) +  b_{n}c_{n}(x) ) = 0
}

に対して、 1 s_{n}(x) c_{n}(x) をそれぞれかけて積分したものを考えれば、

 c = 0 a_{n} = 0 b_{n} = 0 がわかります。

感想

ちょっと元気が無くなってしまい、今回は前半だけです。いろいろ抜けがあると思います、後半の生成系であることを示す方針は全然思いついてないです。ただ関数空間の条件に可積分が必要になりそうですね(多分仮定されてたはず)。

あと、はてなの環境では[tex: ... ]の内部で&が使えないため等式を複数段並べる時とか面倒です。なにか方法があるのでしょうか?

Persistent

Persistentはデータベースアクセスインターフェースを提供するHaskellのパッケージで、DDLDML、などを扱いやすい関数を備えています。

型安全と完結さ、明確な文法という原理に則って開発されていて、PostgreSQLSQLiteMySQL、MongoDBや実験的にRedisもサポートしているそうです。MySQLに関してはjoinをサポートしてい無いそうですが、Esqueletoライブラリによって補完されていると書かれています。また、データベースのマイグレーションも行ってくれるようです。(詳細

データ構造

Persistentはデータベースの構造をどうやってHaskellで表現しているのでしょうか?対応表が載っていたので転記します。

SQL Persistent
Datatypes(VARCHAR, INTEGER, etc) PersistValue
Column PersistField
Table PersistEntity

PersistValueはデータ型、PersistField、PersistEntityは型クラスになっています。

まずは、

Haskell内で記述する必要があるようです。

とりあえず

とりあえずサイトのサンプルを動かしてみます。

{-# LANGUAGE EmptyDataDecls             #-}
{-# LANGUAGE FlexibleContexts           #-}
{-# LANGUAGE GADTs                      #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE MultiParamTypeClasses      #-}
{-# LANGUAGE OverloadedStrings          #-}
{-# LANGUAGE QuasiQuotes                #-}
{-# LANGUAGE TemplateHaskell            #-}
{-# LANGUAGE TypeFamilies               #-}
import Database.Persist
import Database.Persist.TH
import Database.Persist.Sqlite
import Control.Monad.IO.Class (liftIO)

share [mkPersist sqlSettings, mkSave "entityDefs"] [persistLowerCase|
User
    email    String
    password String
    deriving Show
|]

main :: IO ()
main = runSqlite ":memory:" $ do
    runMigration $ migrate entityDefs $ entityDef (Nothing :: Maybe User)
    hogeId <- insert $ User "hoge@fuga.com" "piyo"
    hoge <- get hogeId
    liftIO $ print hoge

プラグマがよくわかってい無いため、なんとも言えませんが記述する部分はshareの次の行のデータ型定義くらいで済んでるのではないかと思います。もしかしたらリレーションとか考えると複雑になるのかもしれませんが。

感想

途中で力が尽きてしまったので、次はいろいろいじりたい。なんだか中途半端なことが溜まっている気がする。

おまけ:Yesod

YesodはHaskellのWebフレームワークです。Haskellによる、型安全でRESTfulで高性能なWebアプリケーション開発の生産性を向上させる目的を掲げているそうです。

PersistentはYesodに組み込まれているそうです。HaskellのWebフレームワークとしてはかなり有名らしく、githubを見るとすでにバージョンは2.5が出ていました。