[Scala]入門 カリー化他
以下の連載の10回目読んだ。9回目のスレッドは浅く見てもよく分からなかったのであとで。
http://www.atmarkit.co.jp/ait/kw/scala.html
名前付き引数
その名の通り、引数指定時に変数名を表記できる。引数の順番も変えられる。
かゆいところに手が届く機能だと感じる。
def div(x:Int,y:Int) = x/y val d = div(y = 5,x = 10)
エンティティのコピー
case classにするとディープコピーを行うcopyメソッドを定義してくれる
copyの引数にはコンストラクタ引数を指定できる。何も指定しなければコピー元の値がそのまま使われる
ここで名前付き引数を使うと便利?
case class X(name:String){ var y:Y = new Y(name + "Y") } class Y(var name:String) val x = X("hoge") val x2 = x.copy() x.y.name = "fuga" println(x.y.name) println(x2.y.name) //ディープコピーされているのでhogeY
引数リスト
(a:Int,b:Int)をdef (a:Int)(b:Int)と書ける。
呼び出しもhoge(1)(2)と別々の括弧になる。
関数を渡す時は引数リストを使うとみやすくなる?
使いどころは後述するカリー化の時?
//関数定義 def myLoop(c:Int, func : => Unit) = { for (i <- 1 to c){ func } } //関数呼び出し myLoop(3){println("hoge")}
引数有の関数を受け取る場合の例。あまり見栄えがよくないか。
//関数定義 def functest(c:Int)(func : (Int) =>Unit ) = { func(c) } //関数呼び出し functest(1){ (c:Int) => println(c+1) }
引数リストの部分適用
引数リスト1つの場合と同じように部分適用できる。
def sum(a:Int)(b:Int) = a+b val partSum = sum(_:Int)(2) val fSum = sum _ val partSum2 = fSum(_:Int)(2)
カリー化
複数の引数を取る関数を、一つの引数を取る関数のチェインに分割すること
カリー化前
def sum(a:Int,b:Int,c:Int) = a + b + c
カリー化後(冗長に書いたもの)
def sumCurrey(a:Int) : (Int) => ((Int)=>Int) = { def innerB(b:Int) : (Int)=>Int = { def innerC(c:Int) : Int = { return a + b + c } return innerC _ } return innerB _ }
型指定を省略
def sumCurrey(a:Int) = { def innerB(b:Int) = { def innerC(c:Int) = { a + b + c } innerC _ } innerB _ }
innerCを無名関数に
def sumCurrey(a:Int) = { def innerB(b:Int) = { (c:Int) => a + b + c } innerB _ }
innerBを無名関数に
def sumCurrey(a:Int) = {
(b:Int) => (c:Int) => a + b + c
}
最終的にここまでシンプルになる
def sumCurrey(a:Int) = (b:Int) => (c:Int) => a + b + c
カリー化のうれしいこと
後でまとめる。参考
http://qiita.com/KDKTN/items/6a27c0e8efa66b1f7799
なお、カリーとは数理論理学者のHaskell Curryに由来する。