Ramda おすすめ機能ベスト10

Ramdaは関数型プログラミングを補助するJavaScriptライブラリだけど、それとは別に便利な関数もたくさん入っている。便利なものをカウントダウン形式に10個紹介するよ。気になる関数があればAPIドキュメント: http://ramdajs.com/docs/ を見てみよう。

# #01. path:  安全なプロパティアクセス

Objectを連想記憶/辞書型/ハッシュテーブルとして使う際に、深いところにあるデータを抜き取るのがめんどくさい。

```js
const obj = {
  cache: {
    user: {
      id: 123,
      name: 'alice',
    },
    contents: {
     ...
    },
}
```

例えば上記の例だと、名前をとってくるのには `name = obj.cache.user.name` とやればいいんだけど、例えば `obj.cache.user` というキーが存在しない場合は、例外がスローされちゃう。めんどい。そんな時は `R.path` の出番。

```js
R.path(['cache','user','name'], obj) // -> 'alice'
R.path(['cache', 'user', 'name'], { cache: {} }) // -> undefined
R.path(['cache', 'user', 'name'], {}) // -> undefined
```

# #02. range: 連続する数値の生成

`[1,2,3,4,5]` などのように連続するN個の整数からなる配列を作るのが有効な場面がある。`range` を使うとすぐ作れる。N回なんかの処理をしたい！とか、オフセットを付けたいとか。

```js
// 1+2+3+....10
R.range(1, 11).reduce((a, x) => a + x, 0); // -> 55
// generate url
R.range(1,5).map(i => `/index?page=${i}`) // -> ['/index?page=1','/index?page=2'... ]
```

関連: 同じものを何個も作りたい、ってときは repeat もあるけど、癖があるので注意。

# #03. scan: reduceっぽい何か

`reduce` は、配列の値を1個ずつ折りたたんで最終的に1つの値にするけど、`scan`は同じように折りたたむんだけど、途中経過を配列に保持してくれる。reduceのデバッグに使うのもよし、以下の例のように、いい使い道もあるかも。

```js
// calc factorial
R.scan((a, x) => a * x, 1, R.range(1, 6)) // [ 1, 1, 2, 6, 24, 120 ]
```

# #04. clone: ディープコピー

Ramda もディープコピー機能を提供している。普通はLodashとか使うのかもしれないけど、せっかくRamdaをインポートしてるなら使うのもいいかもね。

```js
const obj1 = { a: [1, 2] };
const obj2 = R.clone(obj1)
obj2.a.pop();
obj1.a.length === obj2.a.length // -> false
```

# #05. pipe: 関数をつなげてつなげて

左から右にどんどん関数を適用していくパターン。最初の関数以外は、引数を1つしかとってはいけない。

```js
const getName = obj => obj.name;
const getMsg = name => `hello ${name}`;
const toUpper = str => str.toUpperCase();
const toLoud = str => str.concat('!');

const f = R.pipe(getName, getMsg, toUpper, toLoud);
f({ name: 'alice' });// -> HELLO ALICE!
```

右から左にどんどん関数を適用するのは `compose` だけどこっちのほうが直観的に使える。

# #06. once: 絶対に2回以上呼ばせない

何回呼んでも、実際には 2回目以降は呼ばないというスゴ技。返り値は1回目のものが使いまわされる。

```js
const greetOnce = R.once(() => { console.log('hello'); });
greetOnce()
greetOnce()
greetOnce()
greetOnce()
// hello is printed only once.
```

# #07. memoizeWith: 関数呼び出し結果の保存
もし作った関数がpureであれば、同じ引数で何回も関数呼び出しをするのは計算リソースの無駄づかい。1回関数呼び出しをしたら返り値を覚えておいて、2回目以降は覚えておいた返り値を渡すようにする。

```js
const echo = (val) => { console.log(`calc ${val}`); return val;}
const ecoEcho = R.memoizeWith(R.identity, echo);
ecoEcho(1);
ecoEcho(1);
ecoEcho(2);
// print two lines only.
```

第一引数は、キー作成ロジックであり、よくわからなければ`R.identity`(引数をそのままキーにする)にしておけばよい。

# #08. allPass: N回filterする

`isXXX()` というようなチェックを何回もするような時、例えば、配列を何回もfilterするようなときは、allPassを使うとすっきりした見た目になる。すっきりした見た目はエラーがすくなく、コメントの必要すらなくなる

```js
const isNegative = d => d < 0;
const isEven = d => d % 2 === 0;
const isAllIWant = R.allPass([isNegative, isEven]);
R.range(-4, 10).filter(isAllIWant); // -> [ -4, -2 ]
```
# #09. groupBy: 配列要素をグループ化
配列の要素をいくつかのグループに分けたいことがある。素数とそうでない数だとか、スコアによってAクラス〜Dクラスに分けるとか。`groupBy`はそのための自然な手段を提供してくれる

```js
const byTruth = R.groupBy(o => (o ? 'T' : 'F'));
const arr = [1, 0, -1, '', undefined, null, {}, [], 'hello'];
byTruth(arr);
// -> { T: [ 1, -1, {}, [], 'hello' ], F: [ 0, '', undefined, null ] }
```

# #10. flatten: 配列をきれいに

Qiitaで独自実装している人をよくみる。個人的には使ったことがない。

```js
R.flatten( [1, [2,3], [4,5,[6]] ] ) // -> [1,2,3,4,5,6]
```