「COBOLで書かれた特殊なプログラムなので高齢者しか読めず」というパワーワードに対する反応 というTwitterまとめ記事が話題になっており、自分自身もCOBOLを一度も書いたことがなかったので、これは良い機会だと思いCOBOLでFizzBuzzを実装してみました。
環境はUbuntu 16.04 xenial。Linuxで動くGNU COBOLという物があるらしいのでインストールして、ドキュメントはここにすべてまとまっていたので読みながら実装をしてみました。
インストール
まずGNU COBOLのインストール。元々は Open COBOLという名前だったそうです。
$ sudo apt-get update
$ sudo apt-get -f install
$ sudo apt-get install open-cobol
以上でインストール完了。COBOLコンパイラのバージョンを確認します。
$ cobc --version
cobc (OpenCOBOL) 1.1.0
Copyright (C) 2001-2009 Keisuke Nishida / Roger While
Built Feb 07 2016 10:28:13
Packaged Feb 06 2009 10:30:55 CET
無事 OpenCOBOL 1.1.0 がインストールできました。意外と新しく、そして日本人の方が開発されているのですね。
Hello Worldの実装
次に、HelloWorldのサンプルを参考に実装してみます。
$ vim hello.cbl
IDENTIFICATION DIVISION.
PROGRAM-ID. hello.
PROCEDURE DIVISION.
DISPLAY "Hello World!".
STOP RUN.
編集後、コンパイルして実行。 -x がないと実行形式バイナリではなくシェアードオブジェクトが出力されたので、-x オプションを付けました。細かいオプションはマニュアルを見て対応。
コードとして、最初に定義部分を3行定義しなくてはいけなかったり、命令の最後が .
でなくてはいけなかったり、行番号文インデントが必要だったりといろいろと制約が厳しいということにびっくり。
$ cobc -x -o hello hello.cbl
$ ./hello
Hello World!
特に問題なくHelloWorldを実装できました。最近の言語だと print "Hello World!"
などで出力されたりするので新鮮です。
あと実際には以下のように行番号も入れて実装するらしいのですが(よく知らない)、
000010 IDENTIFICATION DIVISION.
000020 PROGRAM-ID. hello.
000030 PROCEDURE DIVISION.
000040 DISPLAY "Hello World!".
000050 STOP RUN.
この度は、行番号無しで実装していきます。一応この実装でも実行できました。なんかBASICっぽいですね。
集計処理の実装
次にサンプルの集計処理も実装してみます。
$ vim sum.cbl
IDENTIFICATION DIVISION.
PROGRAM-ID. SumOfIntegers.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 n BINARY-LONG.
01 i BINARY-LONG.
01 sumv BINARY-LONG VALUE 0.
PROCEDURE DIVISION.
DISPLAY "Enter a positive integer"
ACCEPT n
PERFORM VARYING i FROM 1 BY 1 UNTIL i > n
ADD i TO sumv
END-PERFORM
DISPLAY "The sum is " sumv.
以上のように実装してみました。データ定義部分とループ実装が増えています。
$ cobc -x -o sum sum.cbl
$ ./sum
Enter a positive integer
100
The sum is +0000005050
こんな感じで問題なく実装できました。
データ定義部分をまとめなくてはならず。業務ではPICという領域確保をしながらデータ構造を構築するようです。あとサンプルにあったsumが予約語で使えませんでした。COBOLは予約語が非常に多いことでも有名な言語だそうです。大変ですね。
FizzBuzzの実装
最後に FizzBuzz を実装します。文法は、 COBOLプログラミング入門 というサイトにきれいにまとまっていたので、コーディングフォーマットやルール含めて一旦確認して実装していきます。
$ vim fizzbuzz.cbl
IDENTIFICATION DIVISION.
PROGRAM-ID. FizzBuzz.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 n BINARY-LONG.
01 i BINARY-LONG.
01 m3 BINARY-LONG.
01 m5 BINARY-LONG.
PROCEDURE DIVISION.
DISPLAY "Enter a positive integer for Fizz Buzz"
ACCEPT n
PERFORM VARYING i FROM 1 BY 1 UNTIL i > n
COMPUTE m3 = FUNCTION MOD(i 3)
COMPUTE m5 = FUNCTION MOD(i 5)
IF m3 = 0 AND m5 = 0 THEN
DISPLAY "FizzBuzz"
ELSE IF m3 = 0 THEN
DISPLAY "Fizz"
ELSE IF m5 = 0 THEN
DISPLAY "Buzz"
ELSE
DISPLAY i
END-IF
END-IF
END-IF
END-PERFORM.
以上のように実装できました。
ELSE IFは本来ない文法なのでIF ELSE文を工夫して配置しています。あと、制御文の中では命令文の終わりを表す .
は入力しないとのことでそこで少しハマりました。文法難しいですね...。あと剰余演算子がないので関数で計算です。意外といろんなものがない...。
$ cobc -x -o fizzbuzz fizzbuzz.cbl
$ ./fizzbuzz
以上を実行すると、
Enter a positive integer for Fizz Buzz
15
+0000000001
+0000000002
Fizz
+0000000004
Buzz
Fizz
+0000000007
+0000000008
Fizz
Buzz
+0000000011
Fizz
+0000000013
+0000000014
FizzBuzz
このように FizzBuzz を実装、実行することができました。お疲れ様でした!
結論
文法は複雑だけども、 COBOLは高齢者以外も読める! ということが体感できました。でもたぶん今後COBOLを書くことは無いんじゃないかなと思いますw 最近良く書くScala/JS/C++/Golangのほうが格段に楽ですね。
なおいろいろCOBOLの文法を調べてたら、自分のターゲッティング広告がすべてCOBOL人材募集している広告になりましたw なおこの度のコードは GitHubのリポジトリにおいてありますので必要があれば使ってください。