再帰的プログラム
再帰的プログラムとは、ある関数内で自分自身の関数を呼び出すプログラム構造です。
ほとんどの言語で利用可能ですが、再帰的プログラムはCOBOLやFortranなど1960年代前後に使われた古い言語では使用できません。
応用情報技術者試験などの問題などでたまに出てきます。
階乗計算
とりあえず例としてKotlinで階乗計算(loopNumFunction)を挙げます。
Jetpack Composeですが以下動作確認済です。
fun loopNumFunction(
loopNum: Int
): Int {
val returnNum: Int =
when (loopNum) {
0 -> 1
else -> loopNum * loopNumFunction(loopNum = loopNum - 1)
}
Timber.tag("loopNumFunction").d("loopNum: $loopNum, returnNum: $returnNum")
return returnNum
}
loopNumFunction内でloopNumFunctionを呼び出してます。
loopNumFunction(loopNum = 3)
としたときの結果は「6」です。
loopNumFunction loopNum: 0, returnNum: 1
loopNumFunction loopNum: 1, returnNum: 1
loopNumFunction loopNum: 2, returnNum: 2
loopNumFunction loopNum: 3, returnNum: 6
ログはこのようになります。
ちなみに、3を入力しているのに「loopNum: 0」が先にログとして出力されているのは、Timber.tagの処理がloopNumFunction内のloopNumFunctionが先に走るからです。
スタック
再帰的プログラムの実行にはスタックが必要です。
スタックとはLIFO(後入れ先出し)のデータ構造で、後で挿入した要素が先に取り出されるというものです。
主プログラム(一番最初に呼ばれたloopNumFunction)が関数(loopNumFunction内で呼ばれたloopNumFunction)を呼び出すときに現在実行しているプログラムの戻り番地をスタックしています。
利用頻度
現場ではあまり再帰的プログラムを利用することはないと思います。
理由としては可読性が悪くバグを埋め込みやすいというのが一番で、再帰的なプログラムが必要だったとしてもfilter関数やmap関数などコレクション関数の方が使い勝手がよいです。