前回は関数型言語特有の値としての関数の使い方を学びました。
今回は特殊な関数の呼び出し方から。
まずはクロージャー。(と前回書くつもりで書き忘れたとこ。)
val addmore0 = (x : Int) => x + more //この書き方ではmoreに値が入ってないからエラーが起こる。
//------------------------------------------
var more = 5
val addmore1 = (x : Int) =>x + more //一応エラーは起きない。でもさぁ、引数以外の外部の値に関数の結果が依存してるってのはなぁ。
//------------------------------------------
def addmore2(more:Int) = (x : Int) => x + more //外部の値moreを使わずに書けた。キャー素敵。
次の関数はその問題点を補ってmore = 5としたのでエラーは起きません。
このときのmoreを自由変数といい、逆にxを束縛変数といいます。
そして、関数リテラルが実行されるときに生成される関数のことを「クロージャー」といいます。
今、moreは自由変数なので、addmore1の呼び出しの時に、 とやると、ちゃんとmoreの値が反映されてi = 999となります。
すなわち、クロージャーは生成時にmoreへの参照をつかんでいます。
でもさぁ、moreって値がバンバン変わるからそれに依存した関数書くってのもなぁ。
ようやく本題のaddmore2関数。
この関数はいわば、「クロージャーを返す関数」です。
例えばこんな感じでつかいます。
val add111 = addmore2(111) //addmore2関数内のmoreの値を111に固定したクロージャーを返す。
val add333 = addmore2(333) //addmore2関数内のmoreの値を333に固定したクロージャーを返す。
val i = add111(21) //x(21) + 111 = 132
val j = add333(21) //x(21) + 333 = 354
生成時に固定された111や333といった値をつかんでいます。
次は名前つき引数とデフォルト値の指定。
def printarea(width:Int = 10,height:Int = 10) = println(width*height)
printarea(15,12) //こうも使えるけど…
printarea(height = 12,width = 15)//こうも使えるし、
printarea() //こうも使えるよ(100が出力されます。)っていう。
次回は関数のカリー化と名前渡し関数です。(いつ終われるんだ?関数。)