COBOL does not have stack variables. Everything is a global variable. There is a loose equivalent of a function, called a paragraph, which can be called using a PERFORM statement, but a paragraph does not have any input or output variables, and no return code, so if you want it to behave like a function, you have to construct some sort of complicated naming convention using your global variables.
I’ve seen real customer COBOL programs with many thousands of global variables. A production COBOL program is usually a giant sequence of MOVEs, MOVE A TO B, MOVE B TO C, MOVE C TO D, MOVE D TO E, … with various PERFORMs or GOTOs, or other things in between. If you find that your variable has a bad value in it, that is probably because it has been copied from something that was copied from something, that was copied from something, that’s the output of something else, that was copied from something, 9 or 10 times.
I was toying around with the idea of coding up a COBOL implementation of 2D Euclidean geometric algebra, just as a joke, as it is surely the worst language in the world. Yes, I work on a COBOL compiler project. The project is a lot of fun, and the people I work with are awesome, but I don’t have to like the language.
If I was to implement this simplest geometric algebra in COBOL, the logical starting place for that would be to implement complex numbers in COBOL first. That is because we can use a pair of complex numbers to implement a 2D multivector, with one complex number for the vector part, and a complex number for the scalar and pseudoscalar parts. That technique has been detailed on this blog previously, and also in a Mathematica module Cl20.m.
Trying to implement a couple of complex number operations in COBOL got absurd really fast. Here’s an example. First step was to create some complex number types. I did that with a copybook (include file), like so:
This can be included multiple times, each time with a different name, like so:
The way that I structured all my helper functions, was with one set of global variables for input (at least one), and if appropriate, one output global variable. Here’s an example:
So, if I want to compute and display a value, I have a whole pile of stupid MOVEs to do in and out of the appropriate global variables for each of the helper routines in question:
I wrote enough of this little complex number library that I could do conjugate, real, imaginary, multiply, inverse, and divide operations. I can run that little program with the following JCL
//COMPLEX JOB //A EXEC PGM=COMPLEX //SYSOUT DD SYSOUT=* //STEPLIB DD DSN=PJOOT.SAMPLE.COMPLEX, // DISP=SHR
and get this SYSOUT:
STEP A SYSOUT: A = .10000000000000000E 01 + ( .20000000000000000E 01) I B = .30000000000000000E 01 + ( .40000000000000000E 01) I CONJ(A) = .10000000000000000E 01 + (-.20000000000000000E 01) I RE(A) = .10000000000000000E 01 IM(A) = .20000000000000000E 01 A * B = -.50000000000000000E 01 + ( .10000000000000000E 02) I 1/A = .20000000000000000E 00 + (-.40000000000000000E 00) I A/B = .44000000000000000E 00 + ( .80000000000000000E-01) I
If you would like your eyes burned further, you can access the full program on github here. It takes almost 200 lines of code to do almost nothing.