高階関数の引数あれこれ
カリー化した関数定義で、引数に渡した高階関数に
別の引数リストの結果を渡すとき、下記のように定義すると
java.lang.AssertionError
となる。
def func1(x: Int)(g: Int => Int): Int = g(x)
ここで注意したいのは、1つ目の引数リストの結果を一度 ローカル変数に持ち、これを公開関数に渡すことで、定義ができる。
def func2(x: Int)(g: Int => Int): Int = { val _x = x g(x) }
同じように、1つ目の引数にMapを渡し、2つ目の引数リストにマップを受取る関数を渡す、 カリーかされた関数を下記のように定義する。
def func3(map: Map[String, List[Int]])(f: Map[String, List[Int]] => Int) = { val _map = map f(_map) }
では1から10までの奇数と偶数の整数リストをもつMapを定義し、これを渡して最小の奇数(つまり1)を返す関数を定義し、
定義したfunc3
を使って、結果を得る。
val argMap = Map("odd" -> List(1, 3, 5, 7, 9), "even" -> List(2, 4, 6, 8, 10)) func3(argMap)(m => m("odd").head)
このようにすれば、先頭の1が返ってくる。
さて、このとき高階関数の側はMapを受取ることが自明であるから、プレースホルダ(_)を利用することができる。
また、ライブラリなどを利用する場合、受取るList部分がList以外のコレクション型であった場合もListとして扱えるように、asInstanceOf[]
を利用すると安全である。
func3(argMap)(_("odd").asInstanceOf[List[Int]].head)