関数型プログラミング脳になる
関数型プログラミング(FRP:Functional reactive programming)を考えるためには以下の原則を意識することが大事です。
【原則1】不変性(Immutability)
【原則2】参照透過性(Referential transparency)
【原則3】遅延評価(Lazy evaluation)
他にもありますが、この3点を重点的に意識することで、関数型プログラミングの考え方に慣れていけることでしょう。
ここではjavascriptでFRPを実現するライブラリとして、bacon.js(https://baconjs.github.io/) を利用して関数型プログラミングをやっていきたいと思います。
まずは説明のため、なかなかコードはでてきません。
【原則1】不変性(Immutability)
変数について。
変数を不変、つまりは変更しないようにする、というものです。
基本的に変数はconstである、と思っておいてよいでしょう。
ただし、全てを不変とするとそのプログラムは意味のないものになってしまいそうなので、「基本的に」ということになります。
【原則2】参照透過性(Referential transparency)
関数について。
同じ入力に対して、出力が毎回同じ値になるようにする、というものです。
つまり、関数が独立して処理でき、その結果は処理順や状態によらない、ということになります。
【原則3】遅延評価(Lazy evaluation)
処理について。
一般的にプログラム式は上から順に処理されていきますが、関数型プログラミングではその限りではありません。
1.まず準備や定義し
2.必要に応じて処理する
という流れになります。この部分がなかなか感覚的に分かりづらいのではないかと思います。
データのフロー(流れ)を意識する
手続き型のプログラミングにおいては、フローチャートというものがあり、処理の流れを考えてプログラミングしていました。関数型プログラミングではフロー(流れ)は「処理」ではなく、「データ」だと意識すると理解がし易いのではないでしょうか。
その際、流れていくデータは集合(数学的な意味で)だととらえると関数型プログラミングっぽいプログラムが書ける気がします。
bacon.jsでやってみる
まずは準備から。bacon.jsは https://github.com/baconjs/bacon.js#compatibility-with-browsers によると、
Bacon.js is not browser dependent, because it is not a UI library.
I have personally used it Bacon.js with Chrome, Firefox, Safari, IE 6+, iPhone, iPad.
Automatically tested on each commit on modern browsers and IE6+.
ほとんどのブラウザで問題なく動くようです。ブラウザだけでなく、node.jsでも、もちろん動きます。
ここではhtmlファイルに書いてブラウザで試してみます。
以下のファイルを用意しました。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>bacon.jsのテスト</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bacon.js/0.7.41/Bacon.min.js"></script>
<script>
//1から9までの数値が入った配列を用意
var arr = [1,2,3,4,5,6,7,8,9];
//二倍して返す関数を用意
var twice = function(n){
return n*2;
}
//baconjsの出番
var stream = Bacon.fromArray(arr);//配列からストリームを用意
stream //データのフロー(流れ)の源流
.map(twice) //twice関数をマッピング
.log(); //ログとして出力
</script>
</head>
<body>
(出力はコンソールで確認)
</body>
</html>
デベロッパーツール、Firebug、エラーコンソールなどブラウザによって呼び名は違いますが、コンソールと統一して説明します。
このファイルでは1から9の数字の集合体を二倍にして返す関数で処理したのちにコンソールへログ出力させています。
上記のhtmlファイルをchromeで開いてみた実行結果です。
(bacon.jsをcdn経由で読み込ませていますので、ネットワーク環境が必要です。)
たしかに、1から9がそれぞれ二倍されているようです。
と、ここまではよくあるチュートリアル的なもので、なんとなくわかったようなわからないような、微妙な感想しか残らないでしょう。自分もそうでした。。
配列の中身を二倍するだけで何の役に立つの、実際のところどうやってつかえばいいの、となっちゃうかと思います。
ではもう少し実践的な処理や他の既存ライブラリとの両立のさせ方の説明として、urlのリストから中身をパースして情報を取り出す、いわゆるスクレイピングの処理をbacon.jsで書くとどうなるか、を書いていきます。