teaching an old dog updated languages

For reasons I won’t get into just yet, I’ve been looking at cleaning up my moldering Python skills. It’s been years since I coded anything of significance in Python, and “back in the day” I did it because I had few other options, one of them being Perl. I refuse to write anything in Perl anymore, even though I started my long journey into interpreted languages with the pink Perl book published in 1991.

In the early days I fell upon Perl like a man dying of thirst falls upon an oasis in a desert. In my case, the desert was a mix of bourne and AWK scripting (and I came away positively loathing TCL). With Perl 4 I could build highly sophisticated tooling completely in Perl, and just use my shell scripts to launch my more sophisticated Perl scripts. I started with Perl sometime around 1993 and kept using it until 2000 when I upgraded to Perl 5. With Perl 5, Perl fell out of favor with me, and Python began to rise in its place. I found that Python, in spite of its FORTRAN-like use of spaces to determine scope, was close to C++ and Java than Perl. I found it easier to user Python, both as wrapper for Java and C++ applications as well as being a powerful development language in its own right.

But time moved on and the reasons for using Python fell away. I stuck with C++ and Java, with occasional forays into JavaScript.

And then, for reasons as I said I won’t go into just yet, I had a need to brush up on my Python skills. Except this time, rather than staying in Python 2, I decided to jump whole sale into Python 3, or 3.4.0. I grabbed a copy of the source tarball off the Python website, unpacked it in my Ubuntu 14.04 VM, built it with the configure/make/make install kabuki dance, and started to work with it.

To refresh my skills I started with simple apps, to get a feel for the basics in Python 3. I quickly put together a factorial application, the source and output of which follows:

#!/usr/bin/env python3

import sys

def fact(n):
    a = 1
    print( n, end="! = ")

    while n > 0:
        a, n = a * n, n - 1

    print(a)

if __name__ == '__main__':

    if len(sys.argv) <= 1:
        print("Factorial calculator. Must call with at least one number as argument.")
        sys.exit()

    for i in range(1, len(sys.argv)):
        fact(int(sys.argv[i]))

There’s not much to say about this application. It has one function (fact()). It can test for command line arguments and print out a message with no arguments. It has a tight, simple iteration in main to walk through any and all arguments. The output shows that Python can easily handle arbitrarily large numbers without invoking special features. That alone is one reason it’s used in scientific computing.

While I don’t like how spacing is used to delineate scope, it does remove the need for curly braces used in other languages such as C++, Java, and Ruby, to name but three. What follows is the same application, this time written in Java 8.

import java.math.BigInteger;

public class Fact {
    public static void fact(String num) {
        System.out.print(num + "! = ");
        BigInteger a = new BigInteger("1");
        BigInteger n = new BigInteger(num);

        while (n.compareTo(BigInteger.ZERO) > 0) {
            a = a.multiply(n);
            n = n.subtract(BigInteger.ONE);
        }

        System.out.println(a.toString());
    }

    public static void main (String[] args) {
        if (args.length < 1) {
            System.out.println("Factorial calculator. Must call with at least one number as argument.");
            System.exit(1);
        }

        for (String number : args) {
            fact(number);
        }
    }
}

The syntax is radically different between the two, which is to be expected. Of significant difference is the use of java.math.BigInteger to match Python’s ability to use numbers of arbitrary size and precision. When I first wrote this I used regular integers (int) and could only calculate factorial 11 (11!) before the integer product became negative (sign overflow) and then went to zero. Using BigInteger solved that problem, but introduced a far more complex coding method. While the Java application is only six lines longer, its fact() function is a lot more complex than the fact() function in the Python example. Whereas the Python code can handle the numbers with the same old syntax, special functions within the BigInteger class have to be used to perform basic math (multiplication and subtraction) and the while loop comparison is a somewhat obscure big class function in Java, while with Python its the straightforward comparison we’ve all come to know and love.

In this specific example, the Python code wipes the floor with the Java code, or at least it does for me. There’s a certain sparse (dare I say beautiful?) elegance with the Python code not needing all the matching curly braces that Java requires (and C++, too, for that matter). From a purely coding standpoint, and with this very very narrow example, I find I prefer writing in Python. Maybe larger, more complex coding projects will continue to favor Python over Java, and then again, maybe not. While I want to continue working this kind of duality and comparison, it’s going to reach a point where I’ll need to make a decision when to use which, and stick to it.

I’m surprised, however, how much I like coding in Python. Have I reached a point in my coding life where I should do the majority of my work in Python, moving on from C++ and Java? Maybe even from JavaScript as well.