🧩今日の学び
・INDEXは値ではなく「位置情報」であり、MOVEではなくSETで操作する存在である
・SEARCH文が正しく動くかどうかは、DATA DIVISION側のINDEX設計でほぼ決まる
・COBOLは「動く処理」よりも「動かない宣言」を読めるようになると一気に楽になる
係長)…よし、ではINDEXとSETいくぞ。
なるお)お願いしまーす!
係)まずは、前回のコードはこれだ。
01 ITEM-TABLE.
05 ITEM-REC OCCURS 5 TIMES
INDEXED BY IDX.
10 ITEM-ID PIC X(3).
10 ITEM-NAME PIC X(10).
01 TARGET-ID PIC X(3) VALUE "003".
SET IDX TO 1
SEARCH ITEM-REC
AT END
DISPLAY "見つかりません"
WHEN ITEM-ID(IDX) = TARGET-ID
DISPLAY "見つけた: " ITEM-NAME(IDX)
END-SEARCH
係)まずはINDEXって何者かってことからだが、SETとINDEXはセットで覚えろ。単体で理解しようとするな。
05 ITEM-REC OCCURS 5 TIMES
INDEXED BY IDX.
このIDXだが、数値変数じゃないぞ。
な)え、でもSET IDX TO 1とか書くじゃないすか。
係)そこが一番の罠なんだよ。
INDEXの正体:数値ではなく「場所」を指す存在
係)INDEXはな
- 配列の位置を指すための内部ポインタ
- 人間が触るための数値じゃない
- コンパイラが管理する“場所指定子”
ということだ。
そのため、PICもないし、VALUEもない。
WORKING-STORAGEの数値とは別物だ。
な)ほえ?
だったら、なんで「1」とか入れちゃってるんです?
係)ここでSETの出番となる。
SET IDX TO 1
いいか、これは、IDX に「数値1」を入れてるんじゃないぞ。
な)…。
係)正確には、IDX を「テーブルの1番目を指す状態に設定している」だ。
な)ふむふむ…
なぜMOVEできないのか:SETが必要になる理由
係)では、もしこう書いたらどうなると思う?
MOVE 1 TO IDX
な)…入りそうですけど、入らないんすよね?
係)コンパイルエラーだな。
MOVE:数値を代入する命令IDX:数値じゃない
そして、
INDEXED BY IDX.
この部分でINDEXを使うと宣言しているわけだから、そもそも型が違うということになるぞ。
つまり違いはこうだ。
| やりたいこと | 正しい命令 |
|---|---|
| 数値を入れる | MOVE / ADD |
| INDEXの位置を変える | SET |
そして「SETは左が目的地」の意味がここで効くんだ。
これ、以前やったな。
SET CT-IX TO 1
PERFORM UNTIL CT-IX > 50
IF CT-COUNTRY(CT-IX) = F-COUNTRY-A(1:2)
ADD 1 TO CT-COUNT(CT-IX)
ADD N-LINE-GROSS TO CT-SUM-GROSS(CT-IX)
EXIT PERFORM
ELSE
IF CT-COUNTRY(CT-IX) = SPACES
MOVE F-COUNTRY-A(1:2) TO CT-COUNTRY(CT-IX)
ADD 1 TO CT-COUNT(CT-IX)
ADD N-LINE-GROSS TO CT-SUM-GROSS(CT-IX)
EXIT PERFORM
END-IF
END-IF
SET CT-IX UP BY 1
END-PERFORM.
な)あ、覚えてますよ!
係長が嘘言ったやつですよね!
左から右にって言ってたのに、右から左になったやつ!
参考:【COBOL 読み1-19】MOVEやSETの違い~水に釘の人生
係)お!覚えてたか、って嘘なんか言ってねーだろ!
SETは英語で読む命令:数値操作ではない
係)これは英語で読むと、Set CT-IX to 1. となって、CT-IXを「1番目」に設定しろとなる。
SETは「状態を変える命令」だから
- 対象(IDX)
- TO
- 値(位置)
の順になる。
MOVEと文の形が違う理由が、ここで来る。
つまり、INDEX操作は英語的でないと破綻するというわけだ。
そして、UP BY / DOWN BYも数値加算じゃないぞ。
これも重要だ。
SET CT-IX UP BY 1
な)これ、CT-IX = CT-IX + 1ってことじゃないんすか?
UP BYは加算ではない:走査という考え方
係)見た目はそう見えるな。
でも実態は、「次の要素を指せ」という 位置移動命令 だ。
ADD→ 数値計算SET UP BY→ インデックス移動
意味が違う。
な)なんでCOBOLはこんな面倒なことするんすか?
係)理由は単純だ。
INDEXは- 実メモリアドレスに近い
- 処理系依存
- 数値として触らせると
- 移植できなくなる
- 最適化できなくなる
だから、INDEXは人間に計算させない設計なんだ。
な)なんかよくわからないすけど…
係)深くは知らなくてもいいが、人間は信用されてないってことだ。
さて、以前のコードをINDEX視点で見たとき、こう読め。
SET CT-IX TO 1
PERFORM UNTIL CT-IX > 50
...
SET CT-IX UP BY 1
END-PERFORM
「CT-IXを先頭に置く」
「今指している要素を処理する」
「次の要素へ移動する」
数値ループじゃない。
走査命令の連なりだ。
な)だからPERFORM VARYINGじゃなくて、SETなんすか。
書き方自体が変わっちゃうと…。むーん…でもINDEXの宣言をちゃんと見ていれば、わかるって話でもありますよね。
係)そういうことだな。
最後にまとめるぞ。
INDEXは 数値じゃないINDEXは 位置INDEXを動かせるのはSETだけSETは- 対象 →
TO→ 値 - 英語として読む
- 対象 →
MOVE/ADDの感覚を持ち込むと必ず転ぶ
おむすび
係)よし、ここまで来たら、もう一段深く行けるな!
次はINDEXとSUBSCRIPT(添字)の違いだぞ!
ここでCOBOL理解が「分かった気」から「使える」に変わるぞ!
な)いやさっきまでSEARCHって言ってなかったすか…?
係)そんなのどうでもいい!次いくぞ!
な)えぇ!?
係長のワンポイント
INDEXは「数」じゃない、配列の中の場所そのものだ。
だからMOVEやADDで触らせないし、SETしか許されていない。SET UP BYは加算ではなく、次の要素へ進めという命令だ。
この一連は計算じゃなく、「走査」を書いていると思え。INDEXを数値だと思った瞬間、COBOLは牙をむく。

コメント