再起呼び出し(再起処理)を3分の動画で理解する
再帰呼び出し(再帰処理)について画像と非常に分かり易い動画を用いて解説していきます。
レベルとしては中~上級者向けの記事になっています。
試験問題にもなるぐらいですので使い方が難しい特殊な機能ですが慣れると大変便利な機能です。
例えばこんなことができます。
フォルダ内の全ての階層へもれなくアクセスして必要な情報を取ってくる
深さ(階層)が一定ではないフォルダ群でもOKです。
簡単にフォルダ内の検索ができるので効率UP間違いなしです!
例えばフォルダの中に画像を沢山収納されている方にとっては大変便利なコードを用意する事ができます。
「階層がバラバラのフォルダ群から*.jpgの画像だけ取り出す」なんていうことも可能です。
今回の記事では再帰呼び出し自体の解説をします。
後半では簡単なコード&動画を使って再帰のロジックを勉強します。
次の記事でフォルダ群から特定の画像を取り出すためのコードを紹介する予定です。
再帰呼び出し(再起処理)とは?というところから勉強したい方はこのまま読み進めてください。
関連記事
次回記事では画像を取得する為のコードを紹介する事になります。この記事のコードを使います。
再帰を勉強しようとしている方ならクラスも理解できます。画像をたくさん使って解説しています。
クラスモジュールを解説VBA|クラスとは何か|本当に難しいのかを3つのポイントから検証
再帰呼び出し(再帰処理)とは
私自身も再帰をうまく説明できななったので調べました。分からない事はChatGPTに聞いてみましょう。
加えてWikipediaの英語版からもコードを引用します。再帰は英語ではRecursionです。
まずは再帰とはどんなものなのか?どんな動きをしているのかを理解しましょう。
再帰で何が出来るのかという具体的は話は次回記事で解説します。
再帰呼び出しは、関数またはサブルーチンが自身を呼び出すことによって実現されます。このテクニックを使用することで、問題をより小さな部分に分割し、それぞれの部分に同じ処理を適用することができます。これにより、複雑な問題を簡潔で効率的なコードで解決することができます。
ChatGPT 「VBA 再帰呼び出しについて分かりやすく教えて」の回答から抜粋
- 基本ケース(終了条件)を定義する: 再帰呼び出しは、ある条件が満たされたときに終了する必要があります。この条件を基本ケースと呼びます。
- 自己呼び出しを行う: 分割した問題に対して、同じ関数またはサブルーチンを再帰的に呼び出します。
- 結果を統合する: 再帰呼び出しの戻り値を受け取り、それらを統合して最終的な結果を得る必要があります。
こちらがWikipediaから引用したコードです。
In computer science(コンピューターサイエンスでは の中から抜粋)
VBAのコードではないのですがVBAが分かる方なら意味はわかりますよね。
def factorial(n): if n > 0: return n * factorial(n - 1) else: return 1Wikipedia(英語)再帰から抜粋
3つの要件
ChatGPTは便利ですね。ポイントをまとめてくれました。
再帰はコードを構成する様々な要素(機能)の中の1つです。
以下3つの要件を持ったコードを書く事で再帰呼び出しを含んだプロシージャを用意する事ができます。
- 終了条件を決める
- 自己呼び出しを行う
- 結果を結合する
Wikipediaに掲載されているコードを用いる事で3つの要件を満たす再帰呼び出しのコードが完成します。
ポイントで「自己呼び出し」と書いています。「自分自身を参照」と書いてある文献もありますね。
まだ再帰呼び出しが理解出来てない時はこの「自己呼び出し」が全くイメージできませんでした。
今回は再帰呼び出しをできるだけ簡単に理解する為のマクロを作成しました。
画像と動画を用意していますので「自己呼び出し」含め3つのポイントをおさえてください。
メリット、デメリット
メリットとデメリットを紹介します。
コード量が減るにも関わらず複雑な処理を捌くことができる様になります。
他の言語でも出てくる機能です。考え方は一緒ですのでここで覚えてしまいましょう。
プログラミング初心者の方には本当に難しいです。私理解するまでかなりの時間を要しました。
頑張れば他のコードで代用できてしまうので余計勉強しない・・・という状況でした。
アルゴリズムの本などでも紹介されているので理屈を理解する環境はそれなりにあります。
しかしコードに結びつけるとなると難易度が増します。
コードと解説
まずはコードを紹介します。その後画像でコードの流れを確認いただきます。
最後に動画による解説で理屈を説明していくという建付けになっています。
コード
今回は3の階乗を求めるというコードになります。つまり 3×2×1=6 を導き出すコードです。
ワークシート関数の =FACT(3) と同じ作業です。VBAなら WorksheetFunction.Fact(3) です。
言うまでもないのですがそれだけなら紹介したコードの方がシンプルで簡単です。
今回は再帰の考え方を学んでいただく為にコードを用意しています。ご理解ください。
'*******************************************************
Sub main()
Dim val As Long: val = 0
Dim nbr As Long: nbr = 3
Call factorial(nbr, val)
MsgBox (val)
End Sub
'*******************************************************
Sub factorial(ByRef nr As Long, ByRef vl As Long)
If nr <= 1 Then
vl = 1
Else
Call factorial(nr - 1, vl)
vl = vl * nr
End If
End Sub
'*******************************************************
アウトプット
メッセージボックスに6という数字を出します。
それだけのコードですが重要なのは再帰をコード化して理解する事です。
よってシンプルなアウトプットですがプロセスが重要だという事をご理解ください。
構成
コードだけでは絶対に理解できないので構成を画像にまとめました。
まずは画像から今回のコードはプロシージャが4つになるという事を認識してください。
コードの構成は非常に長くなってしまったので折りたたみました。
できるだけ簡単に理解したい方はコードの構成の下にある動画をご覧ください(約3分ほどの動画です)
- 1mainプロシージャを実行
- 2factorialプロシージャ①を呼び出す
変数nbrは3、変数valは0です
- 3factorialプロシージャ①を実行する
- 4条件分岐でElseに進む
ここで自身(factorialプロシージャ)を呼び出します
変数nrを2にしてから再帰に入ります
- 5factorialプロシージャ②を実行する
- 6条件分岐でElseに進む
再度自身(factorialプロシージャ)を呼び出します
変数nrを1にしてから再帰に入ります
- 7factorialプロシージャ③を実行する
- 8条件分岐でTrueに進む
変数nrが1なので条件Trueとなります
変数vlに1が代入されます
- 9factorialプロシージャ③の終了
- 10factorialプロシージャ②への復帰
演算した結果変数vlに2が代入されます
- 11factorialプロシージャ②の終了
- 12factorialプロシージャ①への復帰
演算した結果変数vlに6が代入されます
- 13factorialプロシージャ①の終了
- 14mainプロシージャへの復帰
メッセージボックスを表示させます
- 15mainプロシージャの終了
動画を使って解説
タイムラインを使って解説を用意しましたが先に書いた様に長くなってしまいました。
これをそのまま解説しても・・・文字を読みたくないですよね。
そこで動画を用意しました。(約3分です)
一連の作業の中でコードの動きと変数の変化を追っていただくと理解につながります。
とても面白い動きをしています。非常に少ないコード量なのですがすごく深いコードです。
mainプロシージャの変数nbrの数値を変える事で変数valの値を可変させることができます。
nbrを5にすると5の階乗となり変数valは120になります。ご自身でトライしてみてください。
キーになるコード
factorialプロシージャの中にあるIfステートメントに全ての要素が詰まっています。
動画の都合上少しだけWikipediaのコードを変形させていますがやっている事は同じです。
If nr <= 1 Then
vl = 1
Else
Call factorial(nr - 1, vl)
vl = vl * nr
End If
- 終了条件を決める ・・・ 変数vlが1になった時が再帰の終了です
- 自己呼び出しを行う ・・・ Callメソッドで自身を呼び出しています
- 結果を結合する ・・・ vl=vl × nrで演算を行います
ポイントを抑えつつ出来るだけ簡単なコードを用意する事が出来ています。
質問、疑問
私が勉強している中で気になった事や質問いただいた事を掲載します。
終了条件
これは絶対必要な条件です。必ず設定してください。
- Qなぜ終了条件が必要なのか
- A
条件を決めてどこかで終了させないと無限ループに入ってしまうからです。
実行中のプロシージャの所在
視覚で確認できなくなるので不安になりますが起動中のプロシージャは消えません。
- Q再帰呼び出し後に取り残された実行中のプロシージャはどうなっているのか
- A
見えないだけでメモリ上に残っています。
前のプロシージャに戻る事ができるのはデータが残っている為です。
便利さに気付けない(なんでこんな事をする必要があるのか)
私は再帰呼び出しを勉強する際に一番感じた事はこの内容でした。
- Q再帰呼び出し自体に何の意味があるのか
- A
この段階では「ややこしい」だけのコードですのでメリットは無いです。
しかし次の記事で紹介するような事が出来るとメリットを感じることが出来ます。
次の記事で具体的な使い方を紹介します。まとめの下にリンクを用意しています。
まとめ
1回読んだだけでは理解するのは非常に難しいです。
繰り返し動画を見て記事を読んでください。合わせて自分でコードを実行する事で理解につながります。
中でも一番の近道は自分でコードを実行してみる事です。動画よりも確実に効果があります。
ステップイン(F8)でコードを動かしてローカルウインドウの値を確認するのは面倒です。
しかしVBAを理解するという事からすると最速最善の方法です。是非試してみてください。
再帰が理解できたら次は応用編です。具体的な事例を使って効果を体感していただきます。
興味のある方は次の記事へ進んでください。