【JavaScript】美味しそうな技🍛（カリー化、部分適用）

# 🍛美味しそうな技...？

そうです。**カリー化**について説明します。カリー？なにそれおいしいの？と思いましたね。カリーは確かにおいしいです。

# 🍛どんな記述？
```js
const curry = a => b => a + b;
curry('カレー')('ライス');
// --> カレーライス
```

例えばこういった記述です。
初見ではナニコレ！？と驚きますね。
この記述は一部省略してあります。省略せずに書くと、

```js
const curry = (a) => {
    return (b) => {
        return a + b;
    }
}
```

こうなります。アロー関数の省略記法だと分かりますね。

簡単に説明すると、
> 引数がひとつのときそれを囲む`()`が省略でき、関数内の記述が一行のとき`{return ...}`の`{}`と`return`が省略できる

というものです。

結果すべての`()`, `{}`, `return`が省略でき、上記の関数を省略記法を用いて記述すると、下のようになります。
```js
const curry = a => 
            b => 
              a + b ;


```
これで、この形が出来上がりました。
```js
const curry = a => b => a + b;
```

# 🍛どう便利ナン？（カレーだけに

簡潔に言うと、カリー化は、**部分適用を簡単に記述**できます。

# 🍛部分適用って何？

部分適用とは、一言でいうと

> 既存の関数の引数の一部を固定し、新たな関数を作ること

です。

数学が好きな方は**予選決勝法**や**一文字固定法**などをイメージしてくださると伝わりやすいかもしれません（言いたかっただけですが、感覚が酷似しています）。

例を見ていただいた方が早いと思うので、こちらをご覧ください。


```js
const ryori = function(a, b){
    // ２つの具材を合わせる関数
    return a + b;
}
const cheeseRyori = ryori.bind(null, 'チーズ');
// 2つの具材のうち1つをチーズに固定する、cheese料理関数
cheeseRyori('カレー'); // チーズカレー
// cheese料理関数と引数のカレーを合わせて、チーズカレーを作る
cheeseRyori('納豆'); // チーズ納豆
// cheese料理関数と引数の納豆を合わせて、チーズ納豆を作る
```
こんな感じで、`ryori関数`の引数を固定し、`チーズ料理だけを作る関数`を作ることができます。
同様に、
```js
const spaghettiRyori = ryori.bind(null, 'スパゲッティ');
```
とすれば`スパゲッティ料理だけを作る関数`を作ることができます。

そして、これにカリー化を組み合わせると、
```js
const ryori = a => b => a + b;
const cheeseRyori = ryori('チーズ');
cheeseRyori('カレー');
cheeseRyori('納豆');
```
このようになり、かなり可読性が増したと思います。

これが<Strong>カリー化のメリット</strong>ですね。

## 🧀注意

### (2022/11/11追記)間違えた説明をしていました。訂正を加えて元の文章は折り畳みにしておきます。

<details><summary>間違えていた内容です。</summary>
ひとつ注意が必要なのですが、ここでアロー関数を使わずに`function`を使ったのは理由があります。理由がわかる人は飛ばしてください。（もしくは教えてください。）

通常の関数とアロー関数の大きな違いのひとつとして、`thisの指すものの違い`があります。

https://qiita.com/suin/items/a44825d253d023e31e4d

この記述では[`bind()`メソッド](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Function/bind)を用いています。

`bind()`メソッドは、呼び出された際に this キーワードに指定された値が設定される新しい関数を生成します。

おそらくこのthisの参照先の違いが原因で、アロー関数では思ったように動きませんでした。

:::note alert
アロー関数を用いた場合でも問題なく動きました。
既に記事をご覧になった方、申し訳ございません。
:::

</details>

# 🍛実際いつ使うん？

ここまでの説明ではカリー化、というより部分適用の魅力が十分に伝わっていないかもしれません。

先ほど部分適用とは

> 既存の関数の引数の一部を固定し、新たな関数を作ること

と言いましたが、これが同時にメリットにも繋がります。

もうひとつ例を挙げます
日付、料理名、美味しいか否か(真偽)を受け取り、文字列を生成する関数です。
この文字列を用いて**料理日記**を付けることを想定してください。

まずはカリー化も部分適用も用いない場合の記述です。
```js
const cookMemo = ( date, dish, isDelicious) => 
    `${date}に${dish}を作りました。美味し${isDelicious?'':'くな'}かったです。`;
let now = new Date();
let today = `${now.getMonth()+1}月${now.getDate()}日`;
cookMemo(today, 'カレー', false);
// --> 11月8日にカレーを作りました。美味しくなかったです。
cookMemo(today, '納豆', true);
// --> 11月8日に納豆を作りました。美味しかったです。
```
この記述だと、最後の文字列を生成する段階で、引数まで見ないと今日の日付で文字列を生成することが分かりません。

しかし、これをカリー化と部分適用を用いて記述してみます。

 ```js
const cookMemo = date => dish => isDelicious => 
   `${date}に${dish}を作りました。美味し${isDelicious?'':'くな'}かったです。`;
let now = new Date();
let today = `${now.getMonth()+1}月${now.getDate()}日`;
const todayCookMemo = cookMemo(today); // 部分適用！
todayCookMemo('カレー')(false); 
    // --> 11月8日にカレーを作りました。美味しくなかったです。
todayCookMemo('納豆')(true); 
    // --> 11月8日に納豆を作りました。美味しかったです。
```
どうでしょう。便利そうに感じませんか？
`cookMemo`関数のから日付を固定し、新しく今日のメモを作る`todayCookMemo`関数を作りました。これが**部分適用**です。
また関係ないですが、カリー化に至っては別言語を書いているようで楽しいです。


# 🍛以上！🍛

おなかがすいたのでおわります。

# 🍛追記！(2022/11/11)

コメント欄にて、カリー化がうまく働く例を教えていただきました。
```js
const add = n => m => n + m;
[1, 2, 3].map(add(10)); // [ 11, 12, 13 ]
```
簡潔で見やすいですし、10じゃなくて20足したい！なんて場合は`add()`の引数を変えてあげれば良いと一目瞭然なので、便利そうだと感じました。
ただ、同時にカリー化は必要ないという意見も頂いております。
カリー化を敢えて用いることによるメリットや、カリー化以外の手段との比較など意識して最適解を選べるようにしたいですねー！



# 🍛参考記事

https://qiita.com/7shi/items/a0143daac77a205e7962

https://qiita.com/takkyun/items/c6e2f2cf25327299cf03


https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Function/bind

https://don-bu-rakko.com/%E3%80%90haskell%E3%80%91%E3%82%AB%E3%83%AA%E3%83%BC%E5%8C%96%E3%81%A8%E9%83%A8%E5%88%86%E9%81%A9%E7%94%A8%E3%82%92%E5%9B%B3%E8%A7%A3%E3%81%97%E3%81%AA%E3%81%8C%E3%82%89%E8%AA%AC%E6%98%8E%E3%81%97/

https://qiita.com/deBroglieeeen/items/f146afd1cdf1e89c4121

https://ja.javascript.info/currying-partials