🧩今日の学び
・ENDは単なる終了記号ではなく「構造の境界宣言」であり、支配領域を明示するための結界である
・AT ENDはELSEではなく「最後まで探索した結果」のみ発火する特殊条件である
・COBOLを読む力とは、インデントとENDを追い続けて構造のねじれを見抜く力である
係長) そろそろ…か。
なるお) なにがすか?
係) いや、なんでもない。
な) ??
係) 今日はENDをまとめていくぞ。地獄だ。いいな。
な) えー!またぁ!?
係) うるさい!いいからやるぞ!
な) ふわーい……
ENDは「終わり」じゃない、「ここまで」の宣言
係) まず、お前、これ読めるか?
IF A = 1
PERFORM UNTIL B = 10
IF C = 5
DISPLAY "HIT"
END-IF
END-PERFORM
END-IF
な) うーんと… Aが1だったら、PERFORMに入って10までルーピング。
んで、Cが5だったら、HITと表示してEND-IF終了。END-PERFORM。外側END-IFって感じっすよね。
係) なんとなくだと事故の始まりになるぞ。
地獄その1:「このENDどこのやつ?」
な) 正直、END-IF ってどのIFのやつなの!?どこの子なの!?って感じっすね。
迷子の子に服を引っ張られて、大声で泣いちゃって、案件になって、通報されちゃうんすよね。
何もしてないのに逮捕される世の中なんすよね。
係) お前はこの世のリスクみたいなもんだからな。仕方ないだろ。
な) いやん。
係) COBOLはこれらが全部ある。
END-IFEND-PERFORMEND-SEARCHEND-EVALUATE
全部「明示終了符」だ。 つまり、必ず閉じろ。曖昧にするなよ。
なぜこんなにENDが多いかって言うとだ…昔のCOBOLはこうだった。
IF A = 1
DISPLAY "OK".
ピリオドで終了。
だが問題が起きた。
な) 係長に愛人がいたとか?
係) なんでだよ!俺は一途なんだよ!
な) おー!純愛!
係) …って、い、いいから!
これだと、どこまでがIFの範囲かわからんだろ!
ネストが深くなると、ピリオド一つ打つだけで、その外側のIFまで全部強制終了してしまう。そして、事故る。
だから今は「範囲を明示しろ」になったんだ。
つまり、END-IF はただの終わりじゃない。構造の境界宣言なんだ。
な) 境界っすか? んー
教会で協会が境界決めるぅ!そして俺は後悔 いぇー!
みたいな感じですかね。
係) 何言ってんだお前?
いいか、「ここまでがIFの支配領域。ここから外!」 それを明確にするための結界だ。
ネスト地獄とインデントの命
地獄その2:ネスト地獄
IF A = 1
IF B = 2
IF C = 3
DISPLAY "OK"
END-IF
END-IF
END-IF
な) これもうインデント命っすよね。
係) その通り。 COBOLはインデントが命、崩れたら死ぬ。
な) すぐ殺そうとするんだから… 悪い癖っすよ…
係) してねーだろ!
地獄その3:PERFORMと混ざる
PERFORM UNTIL EOF
IF FLAG = "Y"
PERFORM PROCESS-REC
END-IF
END-PERFORM
な) これ、END-PERFORM 忘れたら?
係) ログが真っ赤になる。そして原因探しに30分だな。
な) なんすかその血の池地獄!?
あ、でも池ってなんかスケール感がしょぼい感じしますよねー。
血の銀河地獄ぐらいにバージョンアップしたほうがいいんじゃないすかね。
係) どういうことだよ… ま、お前だけが地獄なら、それでも良いんだが。
な) いやいやいやいや
係) まとめるとこうだ。
ENDはただの終わりではない- 構造の境界宣言
- インデントが命
- ピリオド地獄よりはマシ
つまり「読む力」とは、「ENDを追いかける力」と考えておけ。
COBOLは上から順番に読む言語だが、ENDを追えないと迷子になるからな。
な) 俺、迷子の子うさぎちゃんでいいっすよ…
係) 迷子アライグマとか、殺処分だろ。
な) 自分は、たぬきのくせに(ボソ
係) 聞こえてんだよ!
ループはELSEでは止まらない
な) あ、待ってくださいにー。
ふと思ったんですけど、今回ELSE無いじゃないすか。
ってことはルーピングって10まで絶対行くんすか? それとも見つかった時点でEND-PERFORMなんすか?
係) ふむ。
ELSEが無いことと、ループが止まるかどうかは関係ないんだ。
な) ほー。
係) いいか、止まる条件は2つだ。
UNTILの条件が真になる- 中で
EXIT PERFORMする
ELSEがあろうがなかろうが、これ以外では止まらない。
な) ほー?
係) まず、さっきの形を思い出せ。
PERFORM UNTIL B = 10
IF C = 5
DISPLAY "HIT"
END-IF
END-PERFORM
ここでループを止めている条件はどこだ?
な) えーと…、UNTIL B = 10 っすよね。
係) そうだな。 PERFORM UNTIL は、「条件が真になったら終わる」という意味だ。
じゃあ途中で止まるかというと、止まらない。
C = 5が見つかっても、DISPLAYするだけで、ループ終了条件は変わらない。
な) え、じゃあ「HIT」と表示されたあとも普通に回り続けるんすか?
係) そうだ。10になるまで回る。
途中で止めたいなら、例えば
PERFORM UNTIL B = 10 OR C = 5(条件を足す)EXIT PERFORM(脱出する)
のどっちかが必要になる。
な) あー前世でやったやつですね…。
でも俺、室町時代あたりは麻呂麻呂言って蹴鞠してただけなんで。
係) お前が貴族レベルなわけ無いだろが!
な) ひど!
SEARCHのENDはELSEじゃない
係) 次は、SEARCHのEND地獄だ。
な) なんで、地獄つけたがるのこの人…
SEARCH ITEM-TABLE
AT END
DISPLAY "NOT FOUND"
WHEN ITEM-ID(IDX) = TARGET-ID
DISPLAY "FOUND"
END-SEARCH
な) これ普通じゃないすか?
係) 普通に見えるだろ?ここから崩れる。
地獄その1:AT ENDは「ELSE」じゃない
な) AT END って、IF文でいう ELSE みたいなもんじゃないんすか?
係) 違う。AT END は「探索が最後まで行ったときだけ実行」だったろ。
- WHEN → 条件ヒットで即終了
- AT END → 全部探して見つからなかったら実行
な) そっか、ELSE(条件不一致なら毎回)と勘違いすると事故るわけですなぁ。
地獄その2:END-SEARCH忘れ
SEARCH ITEM-TABLE
WHEN ITEM-ID(IDX) = TARGET-ID
IF FLAG = "Y"
PERFORM PROCESS-REC
END-IF
END-IF *> ← これがやらかし例
IFとSEARCHが混ざると、END-IF と END-SEARCH が交錯する。
な) えーでも間違います?
係) 単純なコードなら間違わないかもしれないが、複雑なコードだとどのENDかを見間違う可能性が高くなっていくってことだ。
これやるとログ真っ赤になるぞ。お前はやるだろうが。
な) きぃぃ!
係) ちなみに閉じ忘れるとより地獄だ。
SEARCH ITEM-TABLE
WHEN ITEM-ID(IDX) = TARGET-ID
IF FLAG = "Y"
PERFORM PROCESS-REC
END-SEARCH *> ← IFを閉じてない!
な) IFを閉じてないってことすかね。
係) そうだ。これだとコンパイルエラーだな。
な) むー。
「END-IF忘れちゃってた、てへ!」が通じないとは…
係) 通じるわけないだろ!
そもそも人間の気持ちは関係ない。COBOLは構造しか見てないんらな。
な) 人をみてー!心を感じてー!このアツいパッションを感じてー!
係) 本当に怖いのはこれだ。
な) あ、スルーすか⋯
IF A = "1"
SEARCH ITEM-TABLE
WHEN ...
PERFORM PROC
END-IF *> !?
END-SEARCH *> !?
な) IFとSEARCHを逆に閉じちゃった。でへへ!
係) 濁点つけるなよ!気持ち悪い。
な) 気持ち悪いって、あんた…
係) これだと、コンパイラによっては「どっちも閉じているからOK!」と通してしまうこともある。
だが、中身の構造はグチャグチャだ。Aが”1“じゃない時にSEARCHが動いたり、その逆が起きたりで、本番で死ぬぞ。
な)何回死ぬんすか…
地獄その3:SEARCHの中でIF
係) 例えばこうだ。
SEARCH ITEM-TABLE
AT END
DISPLAY "NOT FOUND"
WHEN ITEM-ID(IDX) = TARGET-ID
IF FLAG = "Y"
DISPLAY "HIT"
END-IF
END-SEARCH
な) これもうインデントしてないと見られたもんじゃないすね…。
係) SEARCHはAT ENDがある分、さらにインデントが迷子になりやすいからな。
だからインデントは命となるんだ、
な) ほむー。
地獄その4:SEARCH ALLはさらに地獄
係) SEARCH ALL は二分探索だから前提条件があったってことは覚えてるだろ?
な) 天上界にあるクラウドに保存してますよ。人間の英知がぎゅうぎゅうにつまっているあれっす。
係) …つまり、お前の記憶にはないということだよな…
な) 必要なときはクラウドから引っ張り出しますからー!
係) 今がそのときだろが! ったく、これだ。
- テーブルはソート済み
ASCENDING / DESCENDING KEY指定必須
これ忘れると、「見つかるはずのデータが見つからない」。しかもエラー出ないからな。
な) あー言ってましたね。
係) それは覚えてたか。
おむすび
な) しっかし、いろんな地獄があるもんすね。
血の宇宙の外側地獄とか怖すぎですよね。
係) なんでスケールアップさせてるんだよ…。
ま、お前みたいにふわふわやってると必ず地獄見るぞ。
な) 係長はそうやって地獄の鬼たちにやられて、係長の顔が鬼以上に変わっていったんですねー。納得です。
係) うるせーな!どこに納得する要素があるんだよ!
な) あ、前世からそのまんまだったってことっすよね…。すみません。
係) じゃかーしぃ!!
係長のワンポイント
ENDは処理を止める記号じゃない。
ここまでが支配領域だ、と宣言する境界線だ。ELSEが無くてもループは止まらないし、AT ENDはELSEでもない。
構造を勘違いすると、静かにねじれて本番で爆発する。
COBOLを読む力とは、ENDを追い続ける力だ。

コメント