戦略 Scala 日記

素人プログラマの思考のセンス

高階関数の引数あれこれ

カリー化した関数定義で、引数に渡した高階関数に 別の引数リストの結果を渡すとき、下記のように定義すると 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)