[JavaScript] 関数型プログラミングを調べてみた

2015/01/9

こんにちは。きんくまです。

今回は特にオチも何もなく日記的なものです。

年末年始に関数型プログラミングっていうのがなんなのか調べてました。

関数型言語
Haskell, Scala, LISP, OCaml

・関数型プログラミング
関数型言語じゃなくても、関数型っぽく書けるよ

・関数型リアクティブプログラミング(Functional reactive programming = FRP)
関数型プログラミングを利用して、実際のアプリを作るよ

という感じ。
調べただけでそこまでよく分かってません。なのでこのエントリはメモなのです。

本は2冊ほど買ってみました。

ちなみに上の本は通称「すごいH本」というらしいです。

ただ、買ってはみたものの、すごいH本は眺めただけ。下のJavaScript本は半分ほど読み進めて挫折しました、、。

Underscore.jsで関数型プログラミング

上の本で、JavaScriptを使った関数型プログラミングをやっているのですが、本を通して使われているのがUnderscore.jsでした。紹介文の最初の文がこうなってます。

Underscore is a JavaScript library that provides a whole mess of useful functional programming helpers without extending any built-in objects.
(Underscoreは、ビルトインオブジェクトを拡張せずに、たくさんの役に立つ関数型プログラミングヘルパーを提供します。)

なので、Underscore.jsで関数型プログラミングができるそうです。気づかなかったよ。

ためしに次のようなお題を考えてみます。

1. 1から100までの数値を用意する
2. 3で割り切れる数だけを抽出
3. 抽出された数を2倍する
4. それらを全て合計する数を求める

Underscoreでやってみます。

var result = _.range(1, 101)
  .filter(function(value){ return value % 3 == 0;})
  .map(function(value){ return value * 2;})
  .reduce(function(total, value){ return total + value; }, 0)
console.log(result); //3366

入力を関数を通して出力につなげる。
それで、それらを連結させていって最後に目的の何かを抽出する。
みたいなイメージでしょうか。

同じことを命令型プログラミングで書いてみます。

var nums = [];
var i, l;
for(i = 1; i <= 100; i++){
  nums.push(i);
}

var filteredNums = [];
for(i = 0, l = nums.length; i < l; i++){
  if(nums[i] % 3 == 0){
    filteredNums.push(nums[i]);
  }
}

var mappedNums = [];
for(i = 0, l = filteredNums.length; i < l; i++){
  mappedNums.push(filteredNums[i] * 2);
}

var total = 0;
for(i = 0, l = mappedNums.length; i < l; i++){
  total += mappedNums[i];
}
console.log(total);

これは愚直にひとつずつループを回しているので長いですね。最適化するとこうなります。

var total = 0;
for(var i = 1; i <= 100; i++){
  if(i % 3 == 0){
    total += i * 2;
  }
}
console.log(total);

短いですねw ただ、上の関数型っぽく書いた場合については、仕様の変更に対応しやすいという利点があるかもしれません。
関数型で書くとひとつひとつは単純な関数なので、その順番を入れ替えたり、中身を修正したりするのがやりやすいと。
イメージとしては、連結された列車があって、n号車がひとつの関数になっているとします。そのときに、5号車と3号車を入れ変えるみたいな。

私はちょっとやっただけなので、あまり適当なことを書くといけないので、ここはこの辺でおしまいにしておきます。

Bacon.js

JavaScriptでFRPをやるライブラリはいくつかあります。有名そうだったのが以下の2つ。

・Bacon.js
・RxJS

Bacon.jsはRxJSを参考に作られたライブラリです。
で、Bacon.jsの使い方を調べてました。

Baconではキモとなるものが2つあります。EventStreamとPropertyです。

EventStreamは、イベントから出てきたデータの流れです。
ボタンがclickされた、データをajaxで非同期通信したとかそういうの。

Propertyはリアクティブなデータです。EventStreamから変換して作ります。

日本語の参考記事
>> 業務アプリ実装にFRP使ってみた

さきほどのEventStreamとPropertyの関係のイメージ(実際に動きます)
>> Functional Reactive Programming and Bacon.js

上の実際に動くプレゼンをみてみると、クリックイベントをEventStreamにして、2つのクリックイベントがmergeされているということがよくわかると思います。

またチュートリアルでは、クリックイベントとサーバーに問い合わせる非同期処理をEventStreamにしている例がでています。
>> Tutorials

いろいろと概念を調べてチュートリアルやっただけなんですが、面白かったです。新鮮な感じ。
あと関数型プログラミングは、関数を返す(returnする)からCoffeeScriptと相性が良さそうだと思いました。(すっきり書ける)

でFRPの流れでいくと次はよく名前を聞く、ReactiveCocoaをみてみたいのだけど、どうでしょう。
同じようなものなんでしょうか、どうなんでしょうか、、?

>> ReactiveCocoa

※追記 ググったら出てきた、ためになる記事
>> 2010-12-26 なぜリアクティブプログラミングは重要か。
>> Webフロントエンドでリアクティブプログラミング

LINEで送る
Pocket

自作iPhoneアプリ 好評発売中!
フォルメモ - シンプルなフォルダつきメモ帳
ジッピー電卓 - 消費税や割引もサクサク計算!

ページトップへ戻る