Inside COBOL #80 (Python from a COBOL perspective)
Some years ago Gavin Scott from Allegro ported Python to the 3000. I remember seeing it and reading up on it a bit. Python was described as an Object Oriented scripting language authored by Guido van Rossum. Python was being done in his (and his teams) spare time while they worked “normal” jobs. Back in May, the core team was hired by BeOpen.com to strictly develop Python, which has lead to the current 2.0 release in early October (a pretty major upgrade). Let’s hope that someone ports the 2.0 release to MPE/iX.
What you’ve really got to love about the language is that it is named Python after Monty Python, and not the snake. The current debugger is called Idle, after Eric Idle. This really can make for some fun naming conventions and books on the subject where Spam and Eggs is mentioned repeatedly. My new company is making a big investment in time on Python as a desktop and application scripting language and is putting in debugging and visual designers and such, and so I thought that since we were spending all this time on Python, I should probably learn it, at least a bit. I have to say that Python is really the most interesting language I’ve looked at in some time, and will probably be the last language I ever learn (crossing my fingers). Python runs on just about every platform you care to name, so there are environments for Windows as well if you wish to go that route, see the Resources at the end of this column.
I’m not going to get into a huge discertation trying to teach you the language, but I want to illustrate some features that are very cool, and compare them to COBOL so you can get a feel. Remember, Python is Object Oriented, so we can quickly get out of the realm of realistic comparisons. Also keep in mind that I’m new to Python, so there might be a couple of details Im not exactly correct about.
Python requires that variables start with a letter or an underscore, nothing else. Variables are also case sensitive (which I’ve always hated), and a variable can not be a reserved word, but there aren’t that many of those. Variables in Python do not have to be declared before hand, so you can say:
X = 0 # X is now an integer object
X = “Hello” # X is now a string object
X = [1, 2, 3] # X is now a list object (we’ll cover this more later)
In this case, X is changing it’s type each time. In COBOL these would have to be 3 separate variables, and they would have to be declared before use, such as:
01 X PIC S9(4) COMP VALUE 0. 01 X1 PIC X(05) VALUE “Hello”. 01 X2. 03 X2-TABLE PIC S9(4) COMP OCCURS 3. MOVE 1 TO X2-TABLE(1). MOVE 2 TO X2-TABLE(2). MOVE 3 TO X3-TABLE(3).
One of the things I really love about Python is it’s ability work with strings. Let me describe some of the variable types that are going to be unusual to you before I get into some of the string functions, as they return types that you won’t be familiar with otherwise.
First there are Lists. Lists are essentially tables, but they are really collections of arbitrary objects. You don’t have to specify the variable type that is in a List, and you can do all sorts of fun things with them. A List is specified by using , for example:
L1 = [ ] #Creates an empty List object L1 = [1, ‘ABC’, ‘DEF’, 2, 3] # A List with integers and strings L1 = [’ABC’, [’DEF’, GHI’]] # a nested sub-List
As we illustrated earlier, a List in Python would be a table declaration with OCCURS in COBOL, and you also can’t assign values to table members during variable declaration. Now if you want to add to the list, you would say L1.append(‘shawn’) to write to the end of our list. We can sort it with L1.sort(), reverse the order L1.reverse(), we can loop through it with:
for x in L1 print x Will produce 1 ABC DEF 2 3 shawn
In COBOL if the table has been declared with 10 members, and you want to add an eleventh, you are flat out of luck unless you have declared a larger table somewhere that you can move your contents to. There is absolutely no way to do dynamic variable declaration in COBOL. We have covered bubble sorts in COBOL in a previous column, so you already know that it requires at least 5 lines of code and a couple of extra variables to sort a table (although the 2002 standard is supposed to include this as a function). You can however reverse a string in COBOL using the functions that are part of the 89 addendum as in MOVE FUNCTION REVERSE(MY-VAR) TO MY-VAR.
What is interesting in Python is that the indentation is important. We indented the print statement from the ‘for’ statement, and this caused it to be part of the condition, if the next line is also indented, it would also be part of the condition, if it is not indented, then the condition block is done. There are no ‘end’ statements or periods or curly braces to indicate scope. This forces you to make your code a bit more readable. Some people balk at this ‘feature’, but I rather like it. I could have done the above as:
for x in L1: print x
So now let’s talk a bit about strings. Consider the following:
A = 1
B = 2
C = A + B
A = ‘Shawn ‘
B = ‘Gordon’
C = A + B
You essentially get native operator overloading so you can use some standard math operators on strings, you can get a repeating string by using * for example. The above example can be done pretty simply in COBOL with the STRING statement, as in STRING VAR1 ‘ ‘ VAR2 DELIMITED BY SIZE INTO VAR3. The downside to this is the DELIMITED BY, if we use the SIZE parameter, then it will string the entire length of the string, if you only have 4 characters in a 10 character string, then you will have 6 spaces between the words in your new string. You can solve this by saying DELIMITED BY SPACES, however if there is a space in your variable, then the second word will be cut out. So unless you really know what is in your data, you can have some trouble. I’m hoping this get’s solved in the 2002 standard.
Let’s look at some other neat examples of functions you can use on strings:
string.capwords(“now is the time”)
Now Is The Time
string.count(“now is the time”, ‘i’)
string.replace(“now is the time”, ‘ ‘, ‘_’)
String.split(“now is the time”)
[’now’, ‘is’, ‘the’, ‘time’]
What is interesting to note here, is that a list has been returned that is a dynamic array containing each of the words in the phrase, automatically tokenized by the white space. I absolutely love this feature, you don’t have to try and create a table first that wil hold everything, and you have one quick command to parse out your words into an ordered table.
So let’s look at how we would do this in COBOL, we can fake out a couple of the COBOL functions to get what we want, such as:
MOVE FUNCTION UPPER-CASE(VAR1(1:1) TO VAR1(1:1).
This will upshift the first character of a string. For the .capwords function you would need to actually loop through the string a character at a time and use the above syntax on each byte that was non-blank after the last byte was a blank, at least 5 lines of code. To continue our comparison.
INSPECT VAR1 TALLYING SUB1 FOR ALL “i”.
Assuming SUB1 is defined as an integer, this will assign a number equal to the number of ‘i’s in the string.
INSPECT VAR1 REPLACING ALL “ “ BY “_”.
UNSTRING VAR1 DELIMITED BY “ “ INTO VAR2 VAR3 VAR4 VAR5.
As you can see in the case of UNSTRING, you have to know how many variables to unstring into. Usually I set up more than I know I will ever need for this kind of case. But you can see that some of the functions in Python are pretty easy to reproduce in COBOL, but others are a good bit harder.
There are functions to center, right justify, left justify, strip spaces, swap the case of the letters, and others. Doing any of this in COBOL is a real pain, and it’s something I’ve been suggesting to the COBOL committee for years that they change.
This was just a high level quick overview, which hopefully peaked your interest a bit. I’ve included some links that you can use to find out more.
www.jpython.org (Python written in Java, and deployable in Java)
http://linux.com/development/newsitem.phtml?sid=64&aid=10564 (excellent getting started paper)