カリー化
最近「カリー化」っていう単語をよく聞くようになったけど意味が分からないままちょっとだけ気になっていました。
http://www.codecommit.com/blog/scala/function-currying-in-scala (英語キライ)
要するにこういうことらしい
カリーじゃない関数。(以下『ハヤシ』と呼ぶ)
add( 1, 2 ) // 6
カリーな関数。
add( 1 )( 2 ) // 6
もう少し詳しく
ハヤシ関数は、引数を何個か受け取って、関数の中で処理を行い、値を返す。
def hayashiAdd( i :Int, j :Int ) = i + j
カリー関数は、引数を1個だけ受け取って、次に呼ばれるべき関数を返す。
def curryAdd( i :Int ) = ( j :Int ) => i + j
全然わからん!!
Scalaは一行で関数が書けるので気持ちよいのだけど、文法がわからないと意味が分からなすぎるので、もう少し丁寧に書きます。
関数の中身は上に書いた関数と全く同じ内容です。
ハヤシ関数は値を返す。
// 足し算をする関数(ハヤシ) def hayashiAdd( i :Int, j :Int ) :Int = { return i + j }
カリー関数は関数を返す。
// 足し算をする関数(カリー) def curryAdd( i :Int ) :(Int) => Int = { // 関数の中で関数を定義する。 def add( j :Int ) :Int = { return i + j } // 定義した関数を返す return add _ }
関数名の後ろに半角スペースとアンダーバーをつけると関数がオブジェクトになるみたいです。アンダーバーをつけないと関数が実行されてしまう(ような気がします。)
カレーとハヤシを変換してくれる関数
Scalaには、上記のハヤシ関数とカリー関数を変換してくれる関数があります。
http://www.scala-lang.org/docu/files/api/scala/Function$object.html
Function.curried
使い方
関数を渡すとカリー化された関数が返ってきます。
// ハヤシな関数 def hayashiAdd( i :Int, j :Int ) = i + j hayshiAdd( 1, 2 ) // ハヤシをカリーに変換 val curryAdd = Function.curried( hayashiAdd _ ) curryAdd( 1 )( 2 )
「curried」関数は引数が1個だけなので、ドットとカッコを省略することができます。
// ハヤシをカリーに変換 val curryAdd = Function curried hayashiAdd _
引数が1つしかない関数を渡すと怒られます。
// 引数を1つだけ取る関数 def oneArg( i :Int ) = i.toString // 変換しようとしたら怒られた Function curried oneArg _ <console>:6: error: overloaded method value curried with alternatives [a1,a2,a3,a4,a5,b]((a1, a2, a3, a4, a5) => b)(a1) => (a2) => (a3) => (a4) => (a5) => b <and> [a1,a2,a3,a4,b]((a1, a2, a3, a4) => b)(a1) => (a2) => (a3) => (a4) => b <and> [a1,a2,a3,b]((a1, a2, a3) => b)(a1) => (a2) => (a3) => b <and> [a1,a2,b]((a1, a2) => b)(a1) => (a2) => b cannot be applied to ((Int) => java.lang.... Function.curried( oneArg _ ) ^
引数の数が6個以上でも怒られるようです。
// 引数を6つ取る関数 def sixArgs( i :Int, j :Int, k :Int, l :Int, m :Int, n :Int ) = i + j + k + l + m + n // 変換しようとしたら怒られた Function curried sixArgs _ <console>:6: error: overloaded method value curried with alternatives [a1,a2,a3,a4,a5,b]((a1, a2, a3, a4, a5) => b)(a1) => (a2) => (a3) => (a4) => (a5) => b <and> [a1,a2,a3,a4,b]((a1, a2, a3, a4) => b)(a1) => (a2) => (a3) => (a4) => b <and> [a1,a2,a3,b]((a1, a2, a3) => b)(a1) => (a2) => (a3) => b <and> [a1,a2,b]((a1, a2) => b)(a1) => (a2) => b cannot be applied to ((Int, Int, Int, Int... Function curried sixArgs _ ^