Lodash-fp を使って JavaScript で関数合成してみます。
Lodash-fp は有名なユーティリティライブラリ Lodash の関数型プログラミングっぽくかけるモジュールの1つです。
前提知識
- JavaScript の基本的な開発経験があること
- Haskell は比較対象として登場しますが知らなくてもたぶん読めます
簡単な例題から考える
例題: 配列 [7,2,3,6] の各値に1を加えて偶数の値だけ取り出してすべて足す。
- 各要素に1を足す(map)
[7,2,3,6] -> [8,3,4,7] - 偶数の値だけ取り出す(filter)
[8,3,4,7] -> [8,4] - すべての要素を足す(sum)
[8,4] -> 12
上記の問題設定自体には特に意味はありません。
Haskell
愚直にカッコを多用して Haskell で書いてみます。
xs = [7, 2, 3, 6]
sum (filter (\t -> t `mod` 2 == 0) (map (\x -> x + 1) xs))
Haskell with point-free style
Haskell っぽくポイントフリー(関数合成)スタイルで書いてみます。
xs = [7, 2, 3, 6]
f = sum . filter ((0 ==) . flip mod 2) . map (+ 1)
f xs
もっと短くも書けます。
f = sum . filter even . map (+1)
Lodash
次は Lodash を使って JavaScript で書いてみます。
const _ = require('lodash');
const xs = [7, 2, 3, 6];
_.sum(_.filter(_.map(xs, x => x + 1), t => t % 2 == 0));
Lodash with chain
JavaScript っぽく chain
で書いてみます。
const _ = require('lodash');
const xs = [7, 2, 3, 6];
_.chain(xs).map(x => x + 1).filter(t => t % 2 == 0).sum().value();
chain
はやはり最後に必要な value()
が残念な感じがします。
Why using _.chain
is a mistake.
Lodash-fp
Lodash-fp を使って JavaScript で書いてみます。
const fp = require('lodash/fp');
const xs = [7,2,3,6];
fp.sum(fp.filter(t => t % 2 ==0, fp.map(x => x + 1, xs)));
Lodash-fp with compose
最後に Lodash-fp の compose
を使って関数合成して書いてみます。
const fp = require('lodash/fp');
const xs = [7, 2, 3, 6];
let f = fp.compose(fp.sum, fp.filter(t => t % 2 == 0), fp.map(x => x + 1))
f(xs);
compose
の分だけやや長くなるけど、Haskell の関数合成の書き方に近くなりました。
まとめ
Lodash-fp の compose
を使えば JavaScript でも Haskell と似たような順番で関数合成して書けます。