libro
www.tuyano.com
初心者のためのPlay Framework入門

30分でわかる(かも知れない)Scala超々入門! (8/8)

作成:2013-01-10 08:30
更新:2013-01-10 08:30

■カリー化とは?

最後に、Scalaの大きな特徴の一つである「カリー化」について触れておきましょう。

複数の引数を持つメソッドの場合、常に「すべての引数を指定してメソッドを呼び出す」ということになります。何度も呼び出す場合、常にすべての引数を指定して、何回も呼び出しを行うことになります。が、例えば「1つ目の引数は常に同じ値。2つ目の値が違うだけ」というような場合、もっとうまいやり方があってもよさそうなものです。それが「カリー化」と呼ばれる手法です。

カリー化は、例えば2つの引数のあるメソッドがあったとき、「1つ目の引数だけ」のメソッドに、「2つ目の引数を指定した関数を返す」ことで全体の処理が行えるようにする手法です。

これは、実物を見たほうが早いでしょう。まず、簡単なサンプルを挙げておきましょう。
object myapp {

    def main(args: Array[String]) = {
        println("100から200までの合計:" + total(100, 200))
    }

    def total(min: Int, max: Int) = {
        var res:Int = 0
        for(n:Int <- Range(min,max + 1))
            res += n
        res
    }
}
毎度登場した、totalメソッドの例です。引数を2つにし、最小値と最大値を指定して、その間の整数の合計を計算するようにしてみました。これ、例えば「0~100まで」「0~200まで」というように、第1引数の最小値が同じで最大値だけが違う、というような利用の仕方ができればけっこう便利ですね。――そこでカリー化です。
object myapp {

    def main(args: Array[String]) = {
        val curryobj = curryTotal(100)
        println("100から200までの合計:" + curryobj(200))
        println("100から500までの合計:" + curryobj(500))
        println("100から1000までの合計:" + curryobj(1000))
    }

    def curryTotal(min: Int) = (max: Int) => {
        var res:Int = 0
        for(n:Int <- Range(min,max + 1))
            res += n
        res
    }
}
なんだか不思議な形になりましたね。ここではcurryTotalというメソッドを定義してあります。これは、以下のようになっています。
def curryTotal(min: Int) = (max: Int) => ……処理……
curryTotal(min: Int)に、(max: Int)の関数オブジェクトが設定されているような形になっていますね。そしてこれを利用する側では、まず、
val curryobj = curryTotal(100)
としてcurryobjに値を代入しています。これで、curryobjには、(max: Int)の関数オブジェクトが代入された形になります。後はこの定数curryobjを使い、
println("100から200までの合計:" + curryobj(200))
println("100から500までの合計:" + curryobj(500))
println("100から1000までの合計:" + curryobj(1000))
こんな具合に、最大値だけをいろいろと指定して呼び出し処理すればいい、というわけです。もし、両方の引数を指定して利用したければ、
curryTotal(0)(50)
こんな具合にして引数をしていすれば、最小値と最大値をまとめて指定し呼び出すこともできます。どちらのやり方も行えるのがカリー化の利点です。

カリー化は、すぐに理解しないとScalaが使えない!というものではありませんが、Scalaの柔軟さを示すものとして、その考え方と基本的な書き方はぜひ覚えておきたいところです。


――この他にも、Scalaには重要な機能がたくさんあるのですが、「とりあえずPlay Frameworkでスクリプトを書いたりできればいい」ということならば、ここまでの説明が頭に入っていれば十分でしょう。その他のことは、必要に応じて随時補足していくことにします。では、次回からいよいよPlay Frameworkの説明に入りましょう!

※プログラムリストが表示されない場合

AddBlockなどの広告ブロックツールがONになっていると、プログラムリスト等が表示されない場合があります。これらのツールをOFFにしてみてください。

●プログラム・リスト●

●リスト1――カリー化する前の例
object myapp {

    def main(args: Array[String]) = {
        println("100から200までの合計:" + total(100, 200))
    }

    def total(min: Int, max: Int) = {
        var res:Int = 0
        for(n:Int <- Range(min,max + 1))
            res += n
        res
    }
}

●リスト2――カリー化した例
object myapp {

    def main(args: Array[String]) = {
        val curryobj = curryTotal(100)
        println("100から200までの合計:" + curryobj(200))
        println("100から500までの合計:" + curryobj(500))
        println("100から1000までの合計:" + curryobj(1000))
    }

    def curryTotal(min: Int) = (max: Int) => {
        var res:Int = 0
        for(n:Int <- Range(min,max + 1))
            res += n
        res
    }
}
※関連コンテンツ

「初心者のためのPlay Framework入門」に戻る