Forget everything you knew about coding (or perhaps remember, depending on your age)

This Christmas I’m going to embrace the past.

COmmon Business Oriented Language (COBOL) 85 standard was the first language I was taught. Napier University was a feeder into the banking and insurance industries in Edinburgh at the time and they had sizeable COBOL farms. It proved profitable too, as a number of students I knew went to the US to alleviate Y2K bugs in thousands of legacy applications. COBOL had fallen out of favour in US colleges.

I was talking to someone the other day who mentioned that he maintains COBOL legacy applications. Apparently things have gone full circle for the UK, where COBOL is no longer taught so his company outsources to India. I’m not overly surprised COBOL is dying out as an educational tool because as languages go its not like much else – Dijkstra certainly didn’t rate it:

The use of COBOL cripples the mind; its teaching should, therefore, be regarded as a criminal offence.

Who am I to argue with the man who killed the goto statement? Certainly as a language it has issues – the 86 standard wasn’t totally compatible with the previous 74 standard; it has no functions; and it has no pointers. Then again it was in part based around the work of Rear Admiral Grace Hopper, the coolest woman ever in computer science, so it couldn’t be all bad could it? She believed that programming languages in mathematical notation were generally not well understood – COBOL is about as self documenting as it gets. It is a product of its time – for example the first six columns are reserved for sequence numbers, this came about as forms were used to write programs which were in turn converted to punch cards.

An example is the best way to explain this, so I decided to revisit Project Euler’s first problem and code it in COBOL, something I haven’t touched in years. As Rear Admiral Grace Hopper said:

It’s easier to ask for forgiveness than it is to get permission.

Of course we need a compiler, Ubuntu has Open COBOL available:

sudo apt-get install open-cobol

Lets consider the problem again:

If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23.

Find the sum of all the multiples of 3 or 5 below 1000.

My solution is to iterate through every number from 1 to 1000, test if it divides by 3 or 5 without a remainder and if so then add it to a counter. In pseudocode:

For counter = 1 to 1000 Step 1
    If counter % 3 = 0 or number % 5 = 0 Then
        total = total + counter
    End If
End For
Display total

But wait – this is COBOL, a language that doesn’t include the word “terse”. So let’s adapt this to a more verbose piece of pseudocode:

For counter = 1 To 1000
    If counter % 3 = 0 Then
        Set flag To TRUE
    End If
    If counter % 5 = 0 Then
        Set flag To TRUE
    End If
    If flag = TRUE Then
        total = total + counter
        Set flag To FALSE
    End If
    Display total
End For

Right, here we go. Its been a long time.  COBOL is organised into divisions, sections, paragraphs, sentences and statements – all are terminated by a period. There are four divisions:

  • Identification. Unsurprisingly contains information about the program.
  • Environment. This isn’t initially obvious but is concerned with portability – this section allows you to isolate anything that is platform specific. So in theory only the environment division needs changing between platforms.
  • Data. This holds all the variables and has four sections – file (file handling); linkage (used with sub-routines); report (for report writers); and the one you almost always need, working-storage (where all your working variables are).
  • Procedure. Guess what? Yes this is where the program itself is.
Let’s start with the beginning:
        IDENTIFICATION DIVISION.
        PROGRAM-ID. EULER_PROBLEM_ONE.

Not much explanation required there then. We don’t need an environment division, it doesn’t hurt to populate the division name anyway.

The next division requires a little more explanation. We need a working-storage section but COBOL defines variables using level, name, picture clause and optionally a value.

Picture clauses define a variable’s format. Levels allow data to be grouped, for example if you defined a student as having an ID and a name you might have:

01 student.
    02 identifier          PIC A9(7).
    02 name                PIC A(30).

Level numbers are for the most part arbitrary as long as the lower the number the higher the level, with the exception of 66 (deprecated), 77 (individual elements) and 88 (used to define conditions). Picture clauses can use: 9 (digit); A (letter); X (digit or letter); V (decimal point); S (sign). You can use A(30) rather than typing loads of A’s.

That just leaves us a procedure division. If you have ever coded assembler then you’ll probably find this easier than if you’ve used C. You need to describe every step. The main iteration construct we need from our pseudocode is a For Loop. COBOL has a PERFORM statement, you need to increment your counter yourself:

PERFORM UNTIL counter = 3
    ADD 1 TO counter GIVING counter
END-PERFORM.

A general convention is to use upper-case for reserved words and lower-case for variables. Pretty much all operations follow this command’s format – do something (ADD 1) to something (counter) and store it somewhere (counter).

IF condition1 > condition2 THEN
   STATEMENT
ELSE
   STATEMENT
END-IF.

You can nest if statements (there’s no Else If statement). Its not uncommon to find a lot of legacy code that only uses IF statements, why I don’t know because it has a Case statement called EVALUATE.

That just leaves us assignment:

MOVE value TO variable

Putting it all together, you need variables to Hold temporary values used to calculate answers, I always call it junk:

        IDENTIFICATION DIVISION.
        PROGRAM-ID. EULER_PROBLEM_ONE.

        ENVIRONMENT DIVISION.

        DATA DIVISION.
        WORKING-STORAGE SECTION.
        01 total        PIC 999999     VALUE 0.
        01 counter      PIC 9999       VALUE 1.
        01 junk         PIC 999999     VALUE 0.
        01 flag         PIC 9          VALUE 0.

        PROCEDURE DIVISION.
        PERFORM UNTIL counter = 1000
             COMPUTE junk = FUNCTION MOD (counter, 3)
             IF junk = 0 THEN
                 MOVE 1 TO flag
             END-IF
             COMPUTE junk = FUNCTION MOD (counter, 5)
             IF junk = 0 THEN
                MOVE 1 TO flag
             END-IF
             IF flag = 1 THEN
                ADD counter TO total GIVING total
                MOVE 0 TO flag
             END-IF
             ADD 1 TO counter GIVING counter
        END-PERFORM.
        DISPLAY total.
        STOP RUN.

Remember that indentation is important (despite the code formatting here not wanting to do it) – areas A and B take the first 6 characters so you need to begin in column 7.

Save the file as euler.cob, compile and run it:

cobc -x euler.cob
./euler

Giving the correct answer of 233168, albeit without any frills.

Output

Hold on to your hats...

It took me a while to get this to compile – Open COBOL doesn’t care for the AUTHOR statement in the IDENTIFICATION DIVISION so I removed it.

What this snippet of code doesn’t show us is that larger projects are unbelievably verbose, lines and lines of code. Nor does it cover the hilarity of design using Data Flow Diagrams – queuing for hours to collect printouts from the University’s only 132 column printer.

Well that’s been a fun trip down memory lane, I don’t remember why I started this post.

Now get off my lawn.

This entry was posted in Coding, Computing, Ubuntu and tagged , , , . Bookmark the permalink.

2 Responses to Forget everything you knew about coding (or perhaps remember, depending on your age)

  1. Anonymous says:

    Thanks for this – the subject has no relevance to me, but it’s a nice slice of history.

  2. canape says:

    nice blog. Looking forward for more posts like this.

Comments are closed.