This request has already been treated.

  1. acevif
Changes in body
Source | HTML | Preview
@@ -1,76 +1,76 @@
タイトルは釣りではなくて、普通に真面目な話です。
結論だけ書くと、カリー化という手法を使う意義は、概念的には、N個の引数をとる関数という概念を、1個の引数をとる関数だけを使って表現できること、実用的にはそういう風に表現することによって、関数の前からの部分適用が簡単にできることですが、Scalaの場合は前者については、普通にN引数メソッドやN引数関数があるので意味がないし、後者については、そのための専用構文があるので有用性が微妙ということになります。
で、それだと色々すっ飛ばし過ぎなので、カリー化ってそもそも何をするものなのか、についてざっくりと説明します。カリー化というのは、Scalaでいうと、たとえば、2引数の足し算をする関数を
```scala
val add: (Int, Int) => Int = (x, y) => x + y
```
という表現する代わりに、
```scala
val curriedAdd: Int => Int => Int = x => y => x + y
```
という形で表現することです。より一般的にいうと、
```scala
def curry[A, B, C](f: (A, B) => C): A => B => C = x => y => f(x, y)
```
こういうメソッドでやっていることがカリー化ということになります(2引数のとき限定でいうなら)。この`curry`メソッドに対して、最初の`add`関数を以下のようにして渡すと、
```scala
val curriedAdd = curry(add)
```
以下のようにして書けるわけです。
```scala
val pAdd = curriedAdd(2)
val result = pAdd(3)
println(result) // 5
```
さて、こういうことができると何が嬉しいかというと、主に、次のように、一部の引数だけを適用(**部分適用**)することができる、ということが挙げられます。
```scala
val xs = List(1, 2, 3, 4).map(curriedAdd(2))
println(xs) // List(3, 4, 5, 6)
```
しかし、実のところ、Scalaでそれをやりたければ、次のようにプレースホルダ構文を使えばいいのです。
```scala
List(1, 2, 3, 4).map(add(2, _))
```
また、カリー化された関数は部分適用できるといっても、**前からしか**部分適用できないので、プレースホルダ構文の方が汎用性があります(ただし、プレースホルダ構文は純粋に構文的操作であって、型を考慮してくれないので、その点に注意する必要があります)。
-また、Scalaだと、JVMとの相互運用性を考慮して、という都合もあるかと思いますが、以下のように、**複数の引数をとるメソッド**や**複数の引数をとるメソッド**が普通に存在してしまっているので、1引数関数だけで全部表現できる、という概念上の単純化にも特に役に立っていません。
+また、Scalaだと、JVMとの相互運用性を考慮して、という都合もあるかと思いますが、以下のように、**複数の引数をとるメソッド**や**複数の引数をとる関数**が普通に存在してしまっているので、1引数関数だけで全部表現できる、という概念上の単純化にも特に役に立っていません。
```scala
def foo1(a: Int, b: Int, c: Int, d: Int): Int = a + b + c + d
val foo2: (Int, Int, Int, Int) => Int = (a, b, c, d) => a + b + c + d
```
というわけで、ことScalaにおいては、あまりカリー化という操作をすることにあまり意味がない、というのが私の意見です(一般的な概念としてのカリー化を知っておくことは意義があると思います)。
余談ですが、Scalaでは標準ライブラリに`curried`メソッドがあり、以下のようにして使うことができるので、自分でカリー化するための操作を定義する必要はありません。
```scala
val sub: (Int, Int) => Int = (x, y) => x - y
val curriedSub = sub.curried
val pApp = curriedSub(1)
println(pApp(2)) // -1
```
ただ、この `curried` メソッド、私は実用で使ったことが一度もないですし、他のライブラリでもそんなに見かけないという実感があります(他言語から輸入したFP系ライブラリでは、案外あるかもしれませんが、未確認です)。
さらに余談ですが、[Scala研修テキスト](http://dwango.github.io/scala_text/function.html)では、この辺について、
> ただ、Scalaではカリー化のテクニックを使うことは、他の関数型言語に比べてあまり多くありません。
と書いてあります(他人事みたいなので、正確にいうと「書きました」ですが)。しかし、考えてみると、Scalaであんまり使わないカリー化を説明する必要なかったのでは疑惑があり、「関数のカリー化」という節自体を削った方が良いかなーという気がしています。