Collectionでスタックを作る

LWP | Collectionでスタックを作る

Collectionでスタックを作る

Push・Peek・Popで「最後に入れたものから」を追いかける

Copyright © 2026 LWP 山中 一弘

本資料は、出典を明記いただければ、商用・非商用を問わず、ご自由に複製・改変・再配布していただけます。なお、著作権表示は改変せず、そのまま記載してご利用くださいますようお願いいたします。

ストーリー

ナマズさんのところへ、修正Aに続いて修正Bが届きました。「今回はBから確認したい」。ココさんと書類を積んで試してみると、取り出す順序はうまくいきそうです。ところが、Bを見ただけで「一件片付いた!」と言い始めて……。

VBAの変数と短い手続きを読める方に向けた記事です。Collectionの先頭を頂上にする実装を扱います。図は概念図で、修正依頼のやり取りは説明用の物語です。末尾のサンプルはWindows版Excel VBAの標準Collectionだけで実行できます。

1 後から来たBを、先に確認したい

受付順と今回確認したい順序は逆です。まずは、書類を積んで上から取る動きを考えます。

修正Aの後にBが届き、BからAの順に取り出す。頂上のBを先に取る後入れ先出しを二人が確認する。

図1|LIFOはLast In, First Out。「後入れ先出し」を表す。

2 Pushは、先頭に積む

ここではItem(1)を頂上と決めます。空のCollectionにAを入れた後、BをAの前に追加します。

AだけのCollectionへPush Bを行うとB、Aの順になり、Item(1)がB、Item(2)がA、Countが2になる。

図2|TakiLibのcollPushは、空ならAdd、非空ならBefore:=1で先頭に追加する。

3 Peekは、見るだけ

次に処理するものを確かめても、処理待ちの一覧から消してよいとは限りません。

Peekは先頭のBを返すが、Collectionの中身はB、AのままでCountは2から2を維持する。

図3|Peekで得る値と、取得後に残る中身を分けて見る。

4 Popは、読んで取り除く

今度は先頭の値を受け取り、その要素をCollectionから取り除きます。Peekとの違いは操作後に現れます。

PopでBを受け取ってRemove(1)するとAだけが残り、Countは2から1、Item(1)はAになる。

図4|Popは値を取得してから削除する。次の先頭はAになる。

5 空のPopは、エラーになる

Aも取り除けばCountは0です。次の図は、TakiLib Ver 3.5.4のcollPopが空をどう扱うかを示しています。

空のCollectionへTakiLibのcollPopを呼ぶと、Emptyを返すのではなくTK3_ERROR_STATUS、エラー2505を発生させる。

図5|空の扱いは実装の契約。TakiLibではCount=0でエラーを発生させる。

6 順序は、入口と出口で決まる

便利な取り出し方でも、受付を全部逆順にすればよいわけではありません。何をどの順に処理したいかで選びます。

先頭へ入れて先頭から出すとLIFO、末尾へ入れて先頭から出すとFIFOになる。先読みしたトークンXをPushで先頭へ戻す用途を示す。

図6|FIFOは先入れ先出し。先読みの差し戻しでは、戻したトークンを次にもう一度読める。

まとめ

先頭へPushし、同じ先頭からPopすれば、B、Aの順に取り出せます。Peekは確認だけなので件数は変わりません。ナマズさんが気付いたとおり、「見た」と「取り除いた」は別の操作です。

今回の仕掛け

Collection自体にPush・Peek・Popというメソッドがあるわけではありません。追加・取得・削除を組み合わせて、スタックとして使います。末尾を頂上にする実装もできますが、本記事では先頭に統一しました。

参照したTakiLibのcollPushは同じCollectionへの参照を返します。collPopは既定で先頭を削除し、collPeekは削除しない指定でcollPopを呼びます。そのためcollPeekも、空の場合は同じエラーになります。エラー2505はこの版のTakiLibの定義であり、VBA標準Collectionのエラー番号とは区別します。

トークンの差し戻しは、先読みで取得した一つを先頭へ戻す利用例です。解析処理全体が常にスタックになるという意味ではありません。また、CollectionからObjectを取り除いても、別の変数が参照を持っていればその実体は残ります。

今回のソースコードのサンプル

TakiLib内部の基本動作を見える形にした、標準Collectionによる学習用コードです。TakiLibの導入や追加の参照設定は不要です。空の場合は呼び出しを省く例であり、エラー2505を再現するコードではありません。

サンプルコード 先頭のBを見てから取り除く

01

Option Explicit

02

03

Public Sub Test_Main()

04

    Dim x_stack As Collection

05

    Set x_stack = New Collection

06

    Call x_stack.Add("A")

07

    Call x_stack.Add("B", Before:=1)

08

09

    Dim x_value As String

10

    x_value = x_stack.Item(1)

11

    Debug.Print "Peek", x_value, x_stack.Count

12

13

    x_value = x_stack.Item(1)

14

    Call x_stack.Remove(1)

15

    Debug.Print "Pop", x_value, x_stack.Count

16

    Debug.Print "Next", x_stack.Item(1)

17

18

    Call x_stack.Remove(1)

19

    If x_stack.Count = 0 Then

20

        Debug.Print "Empty: Pop is skipped"

21

    End If

22

End Sub

コードの説明

x_stackが容器、x_valueが先頭から受け取る文字列です。最初のAddでAを入れ、Before:=1付きのAddでBを先頭へ入れます。最初のItem(1)は読むだけ、次のItem(1)とRemove(1)の組合せは読んで取り除く操作です。最後は残ったAを削除し、Count=0を確認します。

入力・概要

VBEで空の標準モジュールにコードを貼り、イミディエイトウィンドウを表示してTest_Mainを実行します。シートの値は使わず、AとBの2文字列をコード内で追加します。

結果

順に「Peek B 2」「Pop B 1」「Next A」「Empty: Pop is skipped」が表示されます。実際の表示ではDebug.Printのカンマによって項目間に空きが入ります。Windows版Excel 16.0、Build 20326で掲載コードと状態遷移を確認しました。TakiLib固有の空エラーはソース読解による確認です。

読むポイント

最初の取得後にはRemoveがありません。返る文字が同じBでも、件数と次のItem(1)を見ればPeekとPopの違いが分かります。ここでRemoveするのは「容器から取り除く」操作だけで、実業務の修正完了を判定する機能はありません。

出典メモ

元ネタはTK-035「Collectionでスタックを作る」のS2整理稿。TakiLib Ver 3.5.4のtaki3libUTF8.basにあるcollPush(3499行以降)、collPop(3462行以降)、collPeek(3445行以降)と、TK3_ERROR_STATUSの定義を2026年9月11日に照合しました。TakiLibの説明は実装読解、掲載サンプルは標準Collectionの実行確認に基づきます。

図版はLWPのキャラクター共通資産を参照して本記事用に生成しました。公式画面の転載ではありません。