きくらげ観察日記

好きなことを、適当に。

教養としてCOBOLに触れてみる

教養として一度くらいCOBOLに触れてみなければダメなんじゃないかと思ったので、COBOL入門としてFizz Buzzを書いてみました。

コードはこちら。

000010 IDENTIFICATION DIVISION.                                         this
000020 PROGRAM-ID. FIZZBUZZ.                                            is
000030 AUTHOR. HOGE.                                                    a
000040 DATE-WRITTEN. 2017/01/13.                                        comment.
000050 DATE-COMPILED. 2017/01/13.
000060*
000070 ENVIRONMENT DIVISION.
000080 CONFIGURATION SECTION.
000090 SOURCE-COMPUTER. HOGE.
000100 OBJECT-COMPUTER. HOGE.
000110*
000120 DATA DIVISION.
000130 WORKING-STORAGE SECTION.
000140 77 I PIC 999.
000150 77 R PIC 99.
000160*
000170 PROCEDURE DIVISION.
000180 MAIN.
000190*
000200* this is also a comment.
000210*
000220 MOVE 1 TO I.
000230 PERFORM UNTIL I > 100
000240     COMPUTE R = FUNCTION REM(I, 15)
000250     IF R = 0 THEN
000260         DISPLAY "Fizz Buzz"
000270     ELSE
000280         COMPUTE R = FUNCTION REM(I, 3)
000290         IF R = 0 THEN
000300             DISPLAY "Fizz"
000310         ELSE
000320             COMPUTE R = FUNCTION REM(I, 5)
000330             IF R = 0 THEN
000340                 DISPLAY "Buzz"
000350             ELSE
000360                 DISPLAY I
000370             END-IF
000380         END-IF
000390     END-IF
000400     ADD 1 TO I
000410 END-PERFORM.
000420 STOP RUN.

見るからに異様というか、圧倒的に現在主流のプログラムのコードとはかけ離れた見た目をしています。
先頭から順番に見ていきましょう。

000010 IDENTIFICATION DIVISION.                                         this
000020 PROGRAM-ID. FIZZBUZZ.                                            is
000030 AUTHOR. HOGE.                                                    a
000040 DATE-WRITTEN. 2017/01/13.                                        comment.

各行の先頭1〜6文字目は行番号になっています。あとから行を挿入しやすいように10飛ばしにしてる所が泣けてきますね。
ただ、最近の処理系は書かれた行番号を無視するらしいので、この部分は実質無意味なようです。

各行の7文字目はその行の種類を表します。スペースならプログラムの一部。アスタリスクはコメント、ハイフンなら前の行の続きです。
したがって、

000190*
000200* this is also a comment.
000210*

この部分は全てコメントになっています。*から行末までがコメントというわけではなく、その行の7文字目が*であればその行がコメントになるだけという仕様が素晴らしいですね。

8〜72文字目がプログラム本体で、73〜80文字目はコメントです。従って、最初の4行の右端にある

this
is
a
comment.

はすべてコメントになります。

以上の合計80文字によりプログラムの行が構成されます。なお、1行に81文字以上書くことは許されません。コーディングスタイルとして行ごとの文字数を80〜85文字程度に抑えるのはよくあることですが、それが言語仕様として強制されているのは面白いですね。


以上がCOBOLソースコードにおける各行の意味でした。以上の要求を満たす行を並べることで、COBOLのプログラムを書くことができます。
COBOLのプログラムは4つのDIVISIONからなります。

IDENTIFICATION DIVISION
このDIVISIONにはプログラムのメタデータが書かれています。
プログラム名、作者、書かれた日付、コンパイルされた日付などを書きます。
更新日やコンパイルされた日付くらい自動で管理してほしいものですが、COBOLが作られた当時はそうもいかなかったのでしょう。
COBOLで開発を行っている人たちは、プログラムの修正が完了していざコンパイルとなった時に全員総出でDATE-COMPILEDの更新を行ったりしているのでしょうか。少しシュールですね。

ENVIRONMENT DIVISION
このDIVISIONには、実行環境についての情報が書かれています。
プログラムをコンパイルするマシン名、実行するマシン名、プログラムからアクセスするファイルの情報などを書きます。
実行するマシン名が固定というのは、現在からすると考えられませんね。

DATA DIVISION
このDIVISIONでは、プログラムからアクセスするファイルの書式や、プログラム内で使用する変数の定義などを行います。
このプログラムでは2つの変数、IとRを定義しています。

000140 77 I PIC 999.
000150 77 R PIC 99.

先頭にある'77'は変数の種類。この数字を変えることで、構造体やそのプロパティ等も定義できるらしいです。なぜ77なのかは謎。
PICの後にある999, 99は変数の型を表しています。「999」で3桁の10進数、「99」で3桁の10進数を表します。9999999999のかわりに9(10)とか書いたりもできます。ちなみに、777と書いたからといって8進数になるわけでは無さそうです。

PROCEDURE DIVISION
ここからがプログラム本体です。17行目からようやくプログラムが始まります。

000170 PROCEDURE DIVISION.
000180 MAIN.

プログラム本体が何をやっているかはまあ読めばわかると思うので、特に解説はしません。
しかし、(ある程度冗長に書いているとは言え、)たかがFizzBuzzを書くためにこれだけのことを書かなければいけないというのは驚きですね。現在実用的に使われている言語の中で最も書き方が冗長になる言語の1つがJavaですが、Javaによる同様のアルゴリズムFizz Buzzを書いてみると、

class FizzBuzz {
    public static void main(String[] args) {
        for (int i = 1; i <= 100; i++) {
            if (i % 15 == 0) {
                System.out.println("Fizz Buzz");
            } else if (i % 3 == 0) {
                System.out.println("Fizz");
            } else if (i % 5 == 0) {
                System.out.println("Buzz");
            } else {
                System.out.println(i);
            }
        }
    }
}

15行で収まりました。もっと簡潔な文法の言語、例えばHaskellなら、

{-# LANGUAGE MultiWayIf #-}
import Control.Monad
main = forM_ [1..100] $ \i -> do
  putStrLn $ if | i % 15 == 0 -> "Fizz Buzz"
                | i % 3  == 0 -> "Fizz"
                | i % 5  == 0 -> "Buzz"
                | otherwise   -> show i

import文とLANGUAGEプラグマを入れても7行、実質5行で書くことができます。
僕はコードゴルファーでもポールグレアムでもないので短く簡潔に書けることこそがいい言語である条件だとは言いませんが、同じアルゴリズムを書いた時のコードの長さは、その言語を使った時の生産性を測る指標にはなると思います。
COBOLほど冗長にプログラムを書かなければならない言語も珍しいでしょう。金融系などのミスが許されない環境だからこそ、冗長に書かなければならないというのもあるのでしょうが。