「自分自身を呼び出す」再帰的関数に関するコード記述を読んでも、なかなか理解が追い付かずに折れかけたので、自戒を込めて「再帰処理の流れについて基本的な理解を目指す」をテーマに記事を書いてみたいと思います。
下記のシンプルなコードを用いてどのような流れで関数が実行されているか、考えてみます。
####再帰的関数
1 def recursive(n)
2 p 'a'
3 p n
4 return 1 if n == 0
5 p n
6 n * recursive(n - 1)
7 p 'b'
8 p n
9 end
10
11 p recursive(5)
初見、なぜ数字が0から増えていくのかがまったく分からずに混乱しました。
「関数が関数を内包している」様子をイメージしながら、再帰的関数の仕組みについて、下記のように自分なりにかみ砕いてアウトプットしてみます。
####おおまかな流れ
(1)引数として5が与えられて関数実行
→(2)p "a"から5行目のp nまでが実行される(※当然、後置if文returnは実行されない)
→(3)6行目で、自身の関数recursive(4)が実行される。
→(4)ループのように、上記(2)から(3)が、recursive(0)まで実行される。(※この時点で、「(省略)..."a", 1 , 1」まで処理されている」)
→(5)recursive(0)実行時、 p "a"から3行目のp nまでが実行されたのち、後置if文 returnが実行される。returnにより、recursive(0)関数処理が終了。
→(6)ここからは、巻き戻し?逆行?の様な状態になる。
実行場面がrecursive(1)に戻り、7行目の"b"、8行目のp n(※nは1)が実行され、recursive(1)終了。
→(7)実行場面がrecursive(2)へ戻り、7行目の"b"、8行目のp n(※nは2)が実行され、recursive(2)終了。
→(recursive(4)まで省略)
→(8)実行場面がrecursive(5)へ戻り、7行目の"b"、8行目のp n (※nは5)が実行され、recursive(5)が終了しすべての関数が完結。
→(9)最後に、p recursive(5)(p nと同義で)5が出力され、終了。(※仮にpメソッドを除くと、最後の5は出力されない。)
・・・個人的に再帰的関数はかなり理解が難しいです。
場数をこなして慣れていくのがいいのかなと少し頭を悩ませつつ、筆をおきます。