第19章：Scalaでカリー化と部分適用

突然だけど、実は僕はカリーが大好きなんだ！
だから、Scalaを勉強していて __カリー__ の文字が見えた時、急に親近感が湧いたんだ。 
新宿中村屋のインドカリーみたいでしょ。

でも、インドカリーとカリー化は全く関係ないんだよ。 
そこだけは __絶対__ におさえてね！

そう、今回は __カリー化__ を語ってみるよ。
JavaScriptでも出てくる話だから、知っている人も多いんじゃないかな？

# カリー化とは
カリー化とは __Haskell Brooks Curry__ に因んで名付けられたんだ。
あれ？このHaskellって？そう、なんと、 __Haskell__ という関数型言語も彼に因んで名付けられたんだ。

で、カリー化とは何か？

良く __部分適用__ と同時に語られているんだけど、同じとして語られていることがあったり 
説明しているサイト毎にちょっとずつ違ってたりしていて混乱しやすいんだよね。

かく言う僕も、以下の理解で一旦落ち着いていた。

カリー化とは、 __部分適用をした関数を返すことができる関数を定義すること__

と思ったら、なんとこれが間違っているみたいなんだ！
これはカリー化と部分適用を区別できていない間違いだったんだ。。。

## 改めてカリー化
__複数の引数を取る関数を、1つの引数を取る関数のチェーンに変換すること。__

色々調べて考えた結果、これが一番腹落ちしました。

言葉だけだとわからないでしょ？ 
ソースコードを見てみないと何のことやら全く分からないと思うので 
次から説明してみるよ。

### 複数の引数を取る関数
まず __複数の引数を取る関数__ を用意してみる。

```scala
scala> val add = {(x:Int, y:Int, z:Int) => x + y + z}
add: (Int, Int, Int) => Int = <function3>
```

この関数`add`は`x, y, z`という3つの`Int`の引数を受取り、足し合わせた結果を`Int`で返す関数だ。 

ちなみに`add: (Int, Int, Int) => Int = <function3>`は

```
[関数名]: (引数) => (戻り値) <functionトレイト>
```

ということで、`<functionトレイト>`は引数の数によって`functionN`の`N`の数字が決まる。
関数`add`であれば引数が3なので、`function3`となっている。

### 1つの引数を取る関数のチェーンに変換
次に用意した関数を __1つの引数を取る関数のチェーンに変換__ してみる。 
scalaには`curried`というメソッドが用意されているんだね。

```scala
scala> val addCurried = add.curried
addCurried: Int => (Int => (Int => Int)) = <function1>
```

これでカリー化ができちゃいました！　
カリー化した関数を`addCurried`に束縛しています。

### カリー化した関数を使う
カリー化した関数を使ってみよう！
__チェーン__ を意識して、1個ずつ見てみるよ。

まず関数`addCurried`に1つ引数を与えてみよう！

```scala
scala> val addCurriedWithX = addCurried(1)
addCurriedWithX: Int => (Int => Int) = <function1>
```

続けて2つ目の引数を与えてみる。

```scala
scala> val addCurriedWithXY = addCurriedWithX(2)
addCurriedWithXY: Int => Int = <function1>
```

最後に3つ目の引数を与えるよ！

```scala
scala> addCurriedWithXY(3)
res2: Int = 6
```

値が返ってきた！ 
3つの引数を与え終わったので、やっと関数が評価されたんだ。

ちなみにこんな使い方もできるよ。

```scala
scala> addCurried(1)(2)(3)
res1: Int = 6
```

## Scalaでの一般的なカリー化の実現
そういえばScalaには、`curried`メソッドよりも有名なカリー化がありました。 
以下のように引数を複数の括弧にバラすとカリー化です。

```scala
scala> def addScalaCurried(x:Int)(y:Int)(z:Int) = x + y + z
addScalaCurried: (x: Int)(y: Int)(z: Int)Int
```

ただこれじゃ`curried`メソッドを使った場合と同じかちょっとわかりにいくと思います。 
なのでこうしてみる。

```scala
scala> val addScalaCurriedFunc = addScalaCurried _
addScalaCurriedFunc: Int => (Int => (Int => Int)) = <function1>
```

これって先程作った`addCurried`関数と同じだね。 
こっちのカリー化の方が一般的だと思います。

# 部分適用
複数の引数を取る関数に対して、一部の引数に値を束縛した関数を返すこと。 
ソースで見てみよう。

まず関数を定義する。

```scala
scala> def addPartial(x:Int, y:Int, z:Int) = x + y + z
addPartial: (x: Int, y: Int, z: Int)Int
```

この関数に部分適用をしてみる。
今回は第３引数を部分適用し、第1・第2引数を受ける関数を`addPartialWithX`に束縛してみた。

```scala
scala> val addPartialWithX = addPartial(_:Int, _:Int, 5)
addPartialWithX: (Int, Int) => Int = <function2>
```

そして最後に、関数`addPartialWithX`に2つ引数を与えて評価してみる。

```scala
scala> addPartialWithX(2, 3)
res3: Int = 10
```

カリー化は関数のチェーンだったけど、部分適用はいきなり第3引数を部分適用なんてこともできる。

あとどの引数にも部分適用していない関数もできる。 
その場合は`_`を使うんだ。

```scala
scala> val addPartialNone = addPartial _
addPartialNone: (Int, Int, Int) => Int = <function3>
``` 

カリー化と部分適用、なんか全然違うものに見えてきました。。。

カリー化した関数と部分適用した関数は、結果として評価が同じになったけど、かなり違うモノですね。

# まとめ
カリー化を語ってみたけど、書いている途中に部分適用との違いに悩みまくったよ。 
関数そのもの考え方をもっと勉強しないといけないことに、気づいてしまいました。。。

でもカリー化の利点って、関数を段階的に変換できる所なんじゃないかなと思っている。 
あとは感覚的だけど、builderパターンとかの作り上げるパターンに似ている気がする。 

以下のような、先にクライアントとかデータソースとかを用意して
あとは使い回したいケースで使い易いのかな。

- HTTP通信
- DBアクセス

君は
__ナン派？ライス派？__

僕は __ライス派__ だけどね。