Reduxの勉強3
引き続き、Reduxのレッスン動画を視聴した時のメモです。
- 21: ToDoアプリのリファクタリング。見た目と挙動を分けます。Main container componentからPresentational componentを分離しましょうというはなし。
- 22: container componentは振る舞いを定義するクラスとして作成した。
conponentDidMount
、conponentWillUnmont
メソッドを定義し、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の環境構築です。できるだけ覚えることを減らしたいので、webpack
、babel
、react
を軸に必要最低限なものをインストールします。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
には出力ファイルのパスと名前を記述します。ディレクトリ構造を考えていないので特にパスは指定してません。module
のloaders
という配列に、どのファイルをどのようにビルドするかの設定をオブジェクトで記述します。今回は一つだけです。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.json
のscripts
に記述しちゃうと楽です。
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, c
をobj = {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個くらいあるようです。(間違ってました、後述)
- ToDoアプリを用いて、画面の状態が一つのオブジェクト(State Tree)に対応していることの実演。
- State Treeはリードオンリーで、操作(type)とデータを持ったオブジェクト(Action)によって変更される。
- Pure FunctionとImpure Functionの違い。副作用がないこと(戻り値を返す以外の方法で出力を行わないことかな?)
- StateとActionを受け取り新しいStateを返すのがReducer、これはPure Functionになっている。だから同じStateとActionを入れれば同じStateが必ず得られることが保証される。(ちょっと英語怪しくなってきました...)
- 数字を増やしたり減らしたりするだけのCounter Reducerを例に、ReducerとTestの説明をしている。
expect(...).toEqual(...)
って感じで書いている。またReducerの実装上の注意など説明されていた(未定義なtypeのAction、stateのデフォルト値など) - Reduxの導入と、Storeのもつメソッドの説明。ReduxのcreateStoreメソッドによってReducerを引数にStoreというものが作られている。StoreはsubscribeメソッドによってViewの書き換えを行なったり、stateを保持しているようだ。StoreにActionをdispatchメソッドによって食べさせることで保持しているstateが更新されている。こいつは副作用を担っているっぽいです。
- createStoreの実装に関する説明。getState、dispatch、subscribeの三つを提供してくれるがこれらが何をしているかを説明してくれた。subscribeがあまりわからない...内部に持つlisteners配列を更新するが、filter処理はなにをしている?
- renderにはReactを使おう!その際はコールバックを渡すのがいいよ、という説明。おそらく先ほどのsubscribeのおかげでStoreが変更を反映してくれているんだろうという程度の理解。
- テストにdeepFreezeを使ってイミュータブルな処理をちゃんと書こうという話かな?es6の記法(配列
list
に対して...list
を使うことで中身を展開できる)をつかった小粋な書き方とか勉強になりました。 - 引き続きテストの話。
Object.assign
とes6...object
の記法の説明。自分の英語力だと3点リーダの記法がいいように聞こえたんだけどどうなんだ?
いまさら気がついたのですが、この動画30分ではなく30個の動画だったのですね...
30見ていると何も達成感がないのでとりあえずまとめとしてカウンターアプリを作ってみよう。
と思ったのですが、環境構築がうまくいかずに断念。webpackを勉強しないといけない。
感想
ビルドツールになぜか苦手意識があることが判明しました。なぜ嫌なのだろうか?webpackを調べつつ、Redux触っていきたいです、あわよくばElectronでアプリ作りたいです。
javascriptで波括弧を使ってconst値に分割代入
こんにちは。
クロスプラットフォームのデスクトップアプリがhtml、css、javascriptで作れてしまうフレームワーク「Electron」をちょっと触ってみようと思ったのですが、「Hello, world」する前に気になったことをメモします。 (Electronとはあまり関係ない内容になっています)
疑問
とりあえずElectronの環境を整えました。
mkdir myapp npm init -y cd myapp npm install electron-prebuilt --save-dev
あとは、Quick Start - Electronを参考に進めていきました。
ウィンドウを表示したり、閉じた時の挙動を制御するシステム系の設定をindex.js
(package.json
のmain
プロパティで指定したファイル)に記述するのですが、いざコピペしてやろうと思ってサイトの内容を読んでいるといきなり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
というコミットメッセージを発見しました!
ググってみると次のページが見つかります。
分割代入、という構文だったんですね、初めて知りました。
今日はここにたどり着くまでで消耗してしましました...
gnuplotとFFTW
勉強のため、gnuplot(gnuplot 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)
出力方式、出力先を設定することで、画像ファイルや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"
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_1d
はfftw_plan
を戻り値にもつ関数です。引数として次のものをとります;
int n
: データサイズfftw_complex *in
:入力データ配列fftw_complex *out
:出力データ配列int sign
:フーリエ変換(-1)、逆フーリエ変換(+1)かの設定。定数が用意されています。unsigned flags
:通常はFFTW_ESTIMATE
をつかい、サイズが同じ変換を何回もし、初期化コスト(?)を気にしないならばFFTW_MEASURE
を使うみたいです。
感想
力が尽きてしまい、フーリエ変換前後のグラフを出力することは断念しました。sinをフーリエ変換して、一本だけ立つことを確認するとか、関数の和がどんどん短形関数に近づいていく様をみるとか、やりたいです。
フーリエ変換の練習(前半)
フーリエ変換について知識がないため、ちょっと勉強してみます。証明的なものを載せていますが、考え方を学ぶためのメモなため正確なことを知りたい場合参考書を当たってください。フーリエ変換の雰囲気がわからなくて困っている場合はちょっとは役に立つと思います。(私も同じ状況なので)
フーリエ変換は関数を周波数で分解した表示に変換できるものです。分解の際に現れる各項は連続関数と定数の積ですが、これらの無限の和を考えることで、不連続な関数に関しても分解が得られるということが面白と思いました。通信関係をはじめとして、広い範囲での応用がされています。
元となった理論は、フーリエ級数の研究なのかと思います。フーリエ級数は周期関数に関する表示を与えるものでしたが、フーリエ変換では周期を無限と考えることで、その対象を広げたところが違いです。
考え方の核は、周期を無限と考えることと、関数空間に対して基底による分解を与える感じでしょうか?一部フーリエ級数と変わらないですが。
前提条件としては、微分積分、線形代数(基底とかの話)、複素数(というかオイラーの公式)を知っていれば理解できそうです。
離散フーリエ変換など応用の方面でまだまだ研究されているようで2012年には従来の10倍の変換速度を誇るSFFTといったものも発表されたみたいですね。。。
ということで、数学の勉強方法ってどうするんだろう、としばらく悩んだのですが、ああ、証明を考えてみるのが一番理解できるな、と思い出しました。理解のためにまずはフーリエ級数を証明してみます。なので周期関数の空間について考えます。ちゃんとした参考書みないので記号は適当です、うまくいかなかったらすみません。
周期関数
周期 の関数の空間を と定義します。
内積は、 で定義します。(内積であることは積分の性質からいけるはず)
の基底が、1(定値関数)、、 になることを示せれば、任意の周期関数 は、
という形で表せることがわかります。
証明
前半
基底であることを示すには、一次独立と生成系であることを言わなければいけません。
まずは一次独立を示すために、それぞれの基底候補が直交していることを示します。
より がわかりました。 も同様です。
次に、 と と、 ですが、これはオイラーの公式を使うといけそうです(、 の積の公式を忘れてしまいました...)。
以下の等式が成立します。(記述が面倒なので、 とします。)
一方、
なので、
が成り立ちます。さらにの符号を変えた、 から、
よってこれを使うと、
つまり、、、 は直行することがわかります。
以上のことから、
に対して、、、 をそれぞれかけて積分したものを考えれば、
、 、 がわかります。
感想
ちょっと元気が無くなってしまい、今回は前半だけです。いろいろ抜けがあると思います、後半の生成系であることを示す方針は全然思いついてないです。ただ関数空間の条件に可積分が必要になりそうですね(多分仮定されてたはず)。
あと、はてなの環境では[tex: ... ]
の内部で&が使えないため等式を複数段並べる時とか面倒です。なにか方法があるのでしょうか?
Persistent
Persistentはデータベースアクセスインターフェースを提供するHaskellのパッケージで、DDL、DML、などを扱いやすい関数を備えています。
型安全と完結さ、明確な文法という原理に則って開発されていて、PostgreSQL、SQLite、 MySQL、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
が出ていました。
pingを知ろう
こんにちは。
シンプルなものって素敵ですよね。自分が好きなものは包丁とまな板です。大工道具もなかなか素敵です。
本当のところはよくわかってないですが、今日はシンプルそうで、使いこなせるとカッコ良さそうな、ping
コマンドについてメモしました。(BSD)
ping(píŋ)とは?
まずはターミナルからman ping
を実行してマニュアルを確認します。
NAME ping -- send ICMP ECHO_REQUEST packets to network hosts
ICMPとはInternet Control Message Protocol
の略で、IP通信の制御や通信状態の調査などを行なうためのものです。
ECHO_REQUESTとは「エコー要求」と訳されていて、通信可能なら応答するよう要求するICMPのメッセージの一種です。
ping
はICMPでネットワークホストにエコー要求パケットを送るコマンド、
つまりネットワークを通して「大丈夫ですか?」と聞くコマンドということみたいです。
オプション
単純にping XXX.XXX.XXX.XXX
を実行すると、XXX.XXX.XXX.XXX
へパケットが送られ続けます。制御するオプションの一部をメモします。
オプション | 内容 |
---|---|
-c count |
count 回のパケット送信を行った後停止する |
-i wait |
パケット送信毎にwait 秒の間隔(interval?)待機する |
-t timeout |
timeout 秒過ぎたら停止する |
-W waittime |
応答がwaittime 秒過ぎたら画面表示しない(最終的には遅れた応答も統計情報として反映はする) |
パケットが見たい
-p pattern
というオプションでは送信するパケットの内容を変更できるようです。
しかしターミナルからはパケットの内容は見えないため(やり方があるのかもしれませんが)、確認できません......
それだとちょっと寂しいので、脱線してOS Xでパケットを見る方法をメモしておきます。
wireshark
ネットワークプロトコル解析ツールのwireshark
を使えばいいようです。オプションなしでhomebrewでインストールするとguiが無いようなので--with-qt
をつけてコマンドを打ちます。
brew install wireshark --with-qt
インストールの仕方が悪かったのか、うまく動きませんでしたが、sudo /usr/local/Cellar/wireshark/バージョン/bin/Wireshark
で直接起動したらいけました。
wi-fiを選択して、icmpでフィルタします。あとは試しにping -p ff 外部のIP
として見ると、icmpのrequestとreplyが交互に表示されました。
パケットの中身を見るとff
がたくさん並んでいて、-p
オプションも効いています!
感想
とりあえずパケットの中身が見れて満足です。これでping
のオプションも少しずつ理解を深めていけそうです。ネットワーク経路なども選択できるようで、その辺りを使いこなしていきたいです。
haskellのパッケージ管理ツールstack
haskellでservantを使いたくて色々調べていたら、サンプルとして上がっているものがことごとくstackというパッケージ管理ツールを想定したものでした。cabal-install
の代わりになるものっぽいです。
stackはhaskellプロジェクトの管理を簡単にしてくれるもので、依存関係の解決とか、テスト実行とか、ベンチマーク測定とか色々機能があるようです。あとGHCi起動時のモジュールのロードを勝手にしてくれるみたいです。
というわけでhaskellのパッケージ管理ツールstackを入れてみます。
参考
正直現在の環境をどうやって入れたか覚えてないのですが、確かhomebrewでcabal-install
とghc
をインストールした気がします。それらを全てアンインストールし、
brew install haskell-stack
を実行しました。
GHCiを使うために、
stack setup
を実行。
stack ghci
でGHCiが起動するようになりました。
runghc hoge.hg
、runhaskell hoge.hs
は
stack runghc hoge.hs
で実行できます。
感想
使えるからいいやではなく、何をしているかちゃんと理解しないといけないですね......
vimの移動コマンド
こんにちは。
よく使っているエディタ、vimについてメモします。
vimには便利な移動コマンドが沢山あって魅力的です、でもなかなか使いこなせていない感じがします。上下左右移動を覚えた後、さらに自由にファイルを編集するための移動コマンドを調べてみました。
基本的な移動
コマンド | 意味 |
---|---|
h |
左へ移動 |
j |
下へ移動 |
k |
上へ移動 |
l |
右へ移動 |
0 |
行左端へ移動 |
$ |
行右端へ移動 |
^ |
文頭へ移動 |
g_ |
文末へ移動 |
折り返された行での移動
基本的なコマンドに対してg
を頭につけると、折り返し時の移動が楽になります。
コマンド | 意味 |
---|---|
gj |
下へ移動 |
gk |
上へ移動 |
g0 |
画面左端へ移動 |
g$ |
画面右端へ移動 |
gm |
画面中央へ移動 |
例えばgj
、gk
は画面で見たままの上下移動になります。
また、g0
、gm
、g$
コマンドは画面上水平方向の位置へ移動します。
g
をつければ画面上で見たままの、上下左右移動、行頭、行末移動になると覚えておくといいと思います。
検索
コマンド | 意味 |
---|---|
f[char] |
カーソル位置から行末方向にある[char]の位置にカーソルを移動 |
t[char] |
カーソル位置から行末方向にある[char]の直前の位置にカーソルを移動 |
F[char] |
カーソル位置から行頭方向にある[char]の位置にカーソルを移動 |
T[char] |
カーソル位置から行頭方向にある[char]の直前の位置にカーソルを移動 |
; |
直近のf、t、F、Tをリピートします |
, |
直近のf、t、F、Tを逆方向にリピートします(つまりfaのあとの,はFa) |
次の行、次の文、次の段落
コマンド | 意味 |
---|---|
+ |
次の行の最初の文字に移動 |
- |
前の行の最初の文字に移動 |
) |
次の文へ移動(文はドットとスペース. で区切ります) |
( |
前の文へ移動 |
} |
次の段落へ移動 |
{ |
前の段落へ移動 |
感想
gif
作成時にタイプミスしないようにするのが大変でした。(作成にはttygif
を使いました。)
...ちょっと再生速度が速いみたいです。
検索で;
、,
を使いこなせば速度が上がるかと思います、,
は忘れがちなので気をつけます。
いずれ画面操作系のコマンド(配置、リサイズ等)についてもメモしておきたいです。
コメントアウト一覧
こんにちは。
コメントアウトの構文を覚えられないです。やっているうちにいずれ覚えるだろうと思っていたのですが、全然覚えられていないです。
プログラミングを初めてすぐの頃、cssのコメントアウトを//
と書いて、レビューで指摘された思い出があります。その頃はrailsでプログラミングしていたので、ruby、erb、html、css、javascriptなどのコメントアウトがごっちゃになっていたみたいです。
そろそろコメントアウトをちゃんと覚えようと思いました。多分随時更新してきますが、とりあえず以下についてメモしておきます。
目次
コメントアウトの構文
Java
class Main { public static void main(String[] args) { // comment System.out.println("hello"); /* comments comments */ } }
Ruby
# comment p 'hello' =begin comments comments (rubocopに`Do not use block comments`と言われました。非推奨なのかな?) =end
html
<!-- comment --> <p>hello</p> <!-- comments comments (コメントアウトの種類は一つですね) -->
css
/* comment */ body:after { content: 'hello' } /* comments comments (これもコメントアウトの種類は一つ) */
javascript
// comment alert('hello'); /* comments comments (Javaと同じと覚えればいいかも) */
haskell
-- comment main = putStrLn "hello" {- comments comments (この複数コメントの記法のルーツはなんだろう?) -}
mysql
-- comment # comment(この構文はpostgresqlにはないみたいです) select "hello"; /* comments comments */
bash
# comment echo "hello" << EOS comments comments EOS
Markdown
<!-- comment --> **hello** <!-- comments comments (htmlと一緒です) -->
感想
内容と全然関係ありませんが、Markdown
でのページ内リンクの貼り方を覚えました。
<a name="target"></a>ここに飛ぶ [ここを押すと](#target)
という具合です。
とりあえず多分コメントアウト覚えました。
データ型と型クラスの違い
「すごいHaskellたのしく学ぼう!」を勉強した時に、データ型と型クラスで混乱してしまったので、メモ書いておきます。
ザックリまとめると、こんな感じです。
- データ型:データ構造を定義するもの
- 型クラス:振る舞いを定義するもの
ちゃんとした内容は「すごいHaskellたのしく学ぼう!」の7章に書いてあります。
- 作者: Miran Lipovača,田中英行,村主崇行
- 出版社/メーカー: オーム社
- 発売日: 2012/05/23
- メディア: 単行本(ソフトカバー)
- 購入: 25人 クリック: 580回
- この商品を含むブログ (73件) を見る
以下簡単な例と概要を書いていきます。
データ型(data)
データ型の例としては、Int
、Word
、Integer
、Float
、Double
、Char
、Bool
、Ordering
や[]
、()
、Maybe
などがあります。
データ型の扱いは他のプログラミング言語におけるデータ型と大体同じかと思います。ただし、定義には2種類のコンストラクタと呼ばれるものが出てくるので注意しなければいけません。
値コンストラクタ(Data Constructor)
値コンストラクタはデータ型の値を作成するために使用する関数です。データ型の定義において等号の右側に記述されます。例を見てみます。
data Foo = Bar Int | Baz Float | Qux Int Float
データ型Foo
の値コンストラクタはBar
、Baz
、Qux
です。例えばBar
値コンストラクタにInt
データ型の値を渡すことでFooデータ型の値を作ることができます。
ghci>let bar = Bar 1 ghci>:t bar bar :: Foo
つまりBar
は
Bar :: Int -> Foo
という関数になっています。
違う例でいくと、基本的なデータ型Bool
ではFalse
、True
という値コンストラクタを持ちます。
data Bool = False | True
False
、True
を定数と考えるか、引数0の値コンストラクタ関数と考えるかは自由ですが、僕は引数0の値コンストラクタと考える方がデータ型の定義が一般化できるので好きです。
型コンストラクタ(Type Constructor)
型コンストラクタはデータ型を変数にとり新たなデータ型を定義します。テータ型の定義では等号の左側に現れます。例をもとに見ていきましょう。
data Maybe a = Nothing | Just a
Maybe
データ型の等号の右側には、二つの値コンストラクタ(引数0、引数1)が並んでいます。ところがJust
コンストラクタは引数のデータ型がa
となっていて、こんなデータ型ないよ、と思うわけです。
一方等号の左側にはMaybe a
という表記が見えます。このMaybe
の部分が型コンストラクタです。この型コンストラクタは色々なデータ型a
に対し、いろいろなデータ型Maybe a
を作ることができると言っています。
実際に使ってみます。
ghci>let maybe_char = Just 'c' ghci>:t maybe_char maybe_char :: Maybe Char
ここではJust
値コンストラクタにChar
データ型の'c'
を渡すことで、Maybe Char
データ型の値maybe_char
を作っています。
Javaで配列の定義でint[]
、String[]
と書いたことや、総称型のワイルドカードの概念にやや似ていますね。
Maybe
自体に直接データ型を指定してデータ型を得ることは関数定義の時などですが、型推論に頼ってばかりの僕にはあまり関係ないみたいです。
ちなみにGHCi
では:t
に続けて型名を入力すれば型の情報を教えてくれます。定義、インスタンスなどを確認したい場合は:i
が便利で結構万能です。
型クラス(type class)
型クラスは、データ型に実装されたり、違う型クラスに継承されたりします。型クラスの例としては、Num
、Enum
、Show
、Read
、Functor
、Applicative
、Monad
...などたくさんあります。
型クラスはある性質を一般化したものだと考えられます。例えばNum
は整数、浮動小数などの「数」という概念が持つべき振る舞いを定義していますし、Enum
は列挙するという振る舞いを定義しています。
データ型には複数の型クラスを実装させることができます。継承も複数可能です。自由です。今回は大変なので継承は扱わず実装のみ見ていくことにします。
型クラスの定義はclass
によって宣言します。
class Hoge a where fuga :: a -> Int
この型クラスを実装したいデータ型Piyo
は、関数fuga
を実装しなければいけません。実装はinstance
で宣言します。
instance Hoge Piyo where fuga Piyo = 0
(例がとても酷くて申し訳ないです...)
例が例なのに具体的ではなかったので、具体的に初期状態でインポートされているNum
型クラスを見てみましょう。
ghci>:i Num class Num a where (+) :: a -> a -> a (-) :: a -> a -> a (*) :: a -> a -> a negate :: a -> a abs :: a -> a signum :: a -> a fromInteger :: Integer -> a
僕がよくデータ型だと間違えてしまうのがこのNum
です。これはInt
、Word
、Float
、Double
などの数値系のデータ型がもつ、足す、引く、かけるといった、数としての振る舞いを定義しています。(ちなみにnegate
は符号の反転、signum
は符号を返しそうです、実際Int
ではそのような実装が与えられます)
これに対しInt
は以下のような実装を与えています。参考
instance Num Int where I# x + I# y = I# (x +# y) I# x - I# y = I# (x -# y) negate (I# x) = I# (negateInt# x) I# x * I# y = I# (x *# y) abs n = if n `geInt` 0 then n else negate n signum n | n `ltInt` 0 = negate 1 | n `eqInt` 0 = 0 | otherwise = 1 {-# INLINE fromInteger #-} -- Just to be sure! fromInteger i = I# (integerToInt i)
...ちょっとよくわかりません。#
はmagic hashと呼ばれるものらしく、後置修飾子として変数に#
を付与できるようにするものみたいです(参考)。I#
はGHC.Types.I#
のことで、おそらくこの中で定義した和や差の処理を実装として与えているのだと思います。
感想
良い例が全然出せず残念でした。申し訳ないです。
収穫としてはghc
がglasgow haskell compiler
の略だと知ったことです。
あとこれだけ書いたらもう、データ型と型クラスをごっちゃにすることはなさそうです。