8歳娘「パパ、関数を合成して？」

## ある日の我が家

娘（8歳）「うぇ〜ん、うぇ〜ん！」

ワイ「どないしたんや、娘ちゃん！？」

娘「うぇ〜ん、足せないよ〜！」

ワイ「足せない？」
ワイ「何が足せへんのや？」

娘「`100`という数値に対して、配列内の数値を全て加算したいのに、できないよ〜！！！」

ワイ「なんや、そんなことかいな！」
ワイ「確かに8歳といったら、`100`という数値に対して配列内の数値を全て加算したいお年頃よな〜！！！」
ワイ「パパに任しとき！」
ワイ「まずは───」

```diff_typescript
    // 配列を準備
    const array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

    // 足し算関数を準備
    const add = (a: number, b: number): number => {
        return a + b;
    };
```

ワイ「↑こうやな」
ワイ「数値が入った配列と、足し算関数を用意したわけや」
ワイ「そんで、`100`に対して全部の数を足してあげなアカンから───」

```diff_typescript
    // 数値 100 に対して、配列の中身を全て加算する
    const result = array.reduce(add, 100);
    
    console.log(result); // => 155
```

ワイ「↑こうや！」

娘「うわぁ〜、ありがとう！パパ！」
娘「でも、これ何が起きてるの？」

ワイ「おお、すまん」
ワイ「分かりにくかったか？」
ワイ「ほな、`add`っていう足し算関数の中で`console.log()`してみよか！」

```diff_typescript
    // 足し算関数を準備
    const add = (a: number, b: number): number => {
+       // どんな計算をしているのか出力
+       console.log(`${a} + ${b}`);
        return a + b;
    };
```

ワイ「↑こうやな！」
ワイ「ほな、もういちど実行してみるで！」

### 実行結果
```shell
100 + 1
101 + 2
103 + 3
106 + 4
110 + 5
115 + 6
121 + 7
128 + 8
136 + 9
145 + 10
```

娘「そっか！」
娘「配列の要素が10個あるから、`add`関数も10回実行されてるんだね！」

ワイ「せやで」
ワイ「引数`a`の方には、合計値が入ってきて」
ワイ「引数`b`の方には、配列の要素が順番に入ってくる感じや！」

娘「そっか、引数`a`の方は合計値なんだね」
娘「でも、1回目の計算の時だけは、初期値の`100`が入って来るんだね」

ワイ「そうそう、そういう感じや！」

娘「ありがとう、パパ！」

## 5分後

娘「うぇ〜ん、うぇ〜ん！」

ワイ「今度はどないしたんや、娘ちゃん！？」

娘「うぇ〜ん、足せないよ〜！」

ワイ「今度は何が足せへんのや？」

娘「配列内のユーザーの年齢を合計したいのに、できないよ〜」

ワイ「なんや、そんなことかいな！」
ワイ「確かに8歳といったら、配列内のユーザーの年齢を合計したいお年頃よな〜！！！」
ワイ「パパに任しとき！」
ワイ「まず、ユーザーの型は───」

```diff_typescript
    // ユーザーは名前と年齢を持っている
    type User = {
        name: string;
        age: number;
    };
```

ワイ「↑こんな感じやな！」
ワイ「そんで、ユーザーさん達を配列に入れてあげるから───」

```diff_typescript
    // ユーザーの配列
    const array: User[] = [
        {
            name: "太郎",
            age: 100,
        },
        {
            name: "二郎",
            age: 200,
        },
        {
            name: "三郎",
            age: 300,
        },
    ];
```

ワイ「↑こうやな！」
ワイ「ほんで、**数値に対してユーザーの年齢を加算する関数**が必要やから───」

```diff_typescript
    // a という数値に対して、ユーザーの年齢を加算する関数
    const addUserAge = (a: number, user: User): number => {
        return a + user.age;
    };
```

ワイ「↑こうや！」
ワイ「ほな、実行してみるで！」

```diff_typescript
    // 実行
    const result = array.reduce(addUserAge, 0);

    console.log(result); // => 600
```

ワイ「お、合計値を求めることができたで！」

娘「うわぁ〜、ありがとう！パパ！」
娘「さっきは───」

> 数値`100`に対して、配列内の数値を順番に足していく

娘「───って感じだったけど」
娘「今回は───」

> 数値`0`に対して、配列内のユーザーの年齢を順番に足していく

娘「───って感じなんだね！」

ワイ「そういうことや！」

## また5分後

娘「うぇ〜ん、うぇ〜ん！」

ワイ「またかいな・・・」
ワイ「これはもう、プログラミングの問題というより**心の問題**やで」
ワイ「一回、病院行った方がええんちゃうか？」

娘「うぇ〜ん、病院やだよ〜！」
娘「足せないよ〜！」

ワイ「しゃあないなぁ・・・」
ワイ「今度は何が足せへんのや？」

娘「関数の足し算ができないよ〜！」

ワイ「関数の足し算なら、こうやないか！」

```diff_typescript
    // 足し算関数
    const add = (a: number, b: number): number => {
        return a + b;
    };
```

娘「それは、**足し算の関数**でしょ！」
娘「私は、**関数の足し算**がしたいの！」

ワイ「関数の・・・足し算・・・？」

娘「そう！」

```diff_typescript
    // 3 を足す関数
    const add3 = (n: number): number => n + 3;

    // 5 を足す関数
    const add5 = (n: number): number => n + 5;
```

娘「↑この、`add3`と`add5`っていう関数を合成して」
娘「`add8`っていう関数を作りたいの！」

ワイ「なんや、そんなことかいな！」
ワイ「確かに8歳といったら、関数を合成したいお年頃よな〜！！！」
ワイ「パパに任しとき！」
ワイ「さっきの応用で行けるで！」
ワイ「さっきは───」

> 数値`0`に対して、配列内のユーザーの年齢を順番に足していく

ワイ「↑こうだったけど、次は───」

> ある数値に対して、配列内の関数を順番に適用していく

ワイ「↑こういう事をすればええんや！」
ワイ「せやから、まずは───」

```diff_typescript
    // 計算を表す型（数値を受け取って、数値を返す関数）
    type Keisan = (n: number) => number;
```

ワイ「↑こう、計算を表す型を定義したで！」
ワイ「ほんで、`add3`と`add5`は───」

```diff_typescript
    // 3 を足す関数
    const add3: Keisan = (n) => n + 3;

    // 5 を足す関数
    const add5: Keisan = (n) => n + 5;
```

ワイ「↑こうやな！」
ワイ「次は、**計算を適用してあげる関数**が必要やから───」

```diff_typescript
    // a という数値に対して、func という計算関数を適用してあげる関数
    const doKeisan = (a: number, func: Keisan): number => {
        return func(a);
    };
```

ワイ「↑こうやな！」
ワイ「そして───」

```diff_typescript
    // 関数を2つ入れた配列を用意
    const array = [add3, add5];

    // 初期値 10 に対して、add3 と add5 を実行
    const result = array.reduce(doKeisan, 10); // => 18
```

ワイ「↑こうや！」

娘「そっか、配列に関数を詰めてあげて、順番に実行する感じなんだね！」
娘「でも、このままだとなんか、**合成してる感じがあんまりしない**から───」

```diff_typescript
    // 関数を合成する関数
    const gousei = (array: Keisan[]) => {
        // 「initialValue に対して array の中の関数を全部実行してくれる関数」を返す
        return (initialValue: number) => array.reduce(doKeisan, initialValue);
    };
```

娘「↑こう、関数にしてみた！」

ワイ「おお、関数を作ってくれる関数やな」

娘「うん、こんな感じで使うの！」

```diff_typescript
    // add3 と add5 を合成して、add8 を作る
    const add8 = gousei([add3, add5]);

    // 実行
    const result = add8(10); // => 18
```

ワイ「おお、ええやないか！」
ワイ「関数を合成してる、って感じするな！」
ワイ「でも、配列を渡すんやなくて───」

```diff_typescript
    // add3 と add5 を合成して、add8 を作る
    const add8 = gousei(add3, add5);
```

ワイ「↑こう、`add3`と`add5`をそのまま渡したいなぁ」

娘「わかった、やってみる！」

```diff_typescript
    // 関数を合成する関数
-   const gousei = (array: Keisan[]) => {
+   const gousei = (...array: Keisan[]) => {
        // 省略
    };
```

娘「↑できた！」

ワイ「おお、そうか」
ワイ「可変長引数にすればいいだけやったな」

娘「うん！」
娘「実行してみるね！」

```diff_typescript
    // add3 と add5 を合成して、add8 を作る
    const add8 = gousei(add3, add5);

    // 実行
    const result = add8(10); // => 18
```

ワイ「おぉ〜、できとるわ」
ワイ「もちろん、こう───」

```diff_typescript
    // 3つの関数を合成
    const add13 = gousei(add3, add5, add5);

    // 実行
    const result = add13(10); // => 23
```

ワイ「3つ以上の関数も合成できるしな！」

娘「わ〜い！」

ワイ「ワ〜イ！」

## まとめ
- `Array.prototype.reduce()`で色々できた

## その日の夜

娘「でも実際、関数合成ってなんの役に立つの？」

ワイ「うーん、例えば、入力フォームのバリデーションをするときに───」

- 10文字以上である事を確認するバリデーション関数
- 500文字以下である事を確認するバリデーション関数

ワイ「↑こう、2つのバリデーション関数を作って」
ワイ「それを合成して───」

- 10文字以上かつ500文字以下である事を確認するバリデーション関数

ワイ「↑こういう関数を作ったりできるで」

娘「へぇ〜、単機能な関数をいくつか作って」
娘「それを合成して別の関数を作れるんだね」

ワイ「そんな感じやな」
ワイ「もっと色々なこともできると思うけど」
ワイ「パパの頭脳ではよく分かってへんわ」
ワイ「あとはChatGPTにでも聞いてや・・・」

**〜おしまい〜**

## 参考文献
- [Array.prototype.reduce() - JavaScript | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce)