As I spent Sunday in a session of "learn enough Perl to successfully program an assignment for Theoretical Computer Science (EECS 343)," I was reminded of what I consider to be one of the most interesting aspects of picking up a new programming language. The challenge I always face with a new language is not the syntax so much as a fundamental shift in the approaches taken to solve a problem. Once you've learned a programming language, it's fairly simple to pick up other languages, especially in the imperative language family. The syntax is simple enough to learn, the keywords are usually similar enough that a search through the index for the keyword that you're used to will show what the keyword you're looking for is, which enables you to look up the syntax. The control structures are fairly universal, and leaving aside the actual differences between names and variables, it's fairly easy to hack a solution in a new language. Therein lies the issue. For the most part, if you stick with the programming paradigm you're familiar with, what you end up programming is a hack. You don't utilize the full set of capabilities of a language, you end up forcing a language to mimic one that you're familiar with. While a number of languages have gained a lot of popularity, no single language has emerged as the be-all-end-all of programming.
One of the paradigm shifts I encountered during my excursion into the world of Perl, was attempting to represent a matrix. The C/C++/Java programmer in me bemoaned the lack of two-dimensional arrays in Perl and began looking for a way to build an array of arrays. Fortunately a friend (thank you Eric) pointed out a simpler solution before I wandered too far down this path. The idea of hashing each cell in the matrix/table I was trying to represent with the key being the cell position simply had not occurred to me. I found myself falling back into a thought process that connected Perl hash-tables to Java collections and Perl arrays to Java arrays.
Another example of a necessary paradigm shift is the difference between POSIX threading in C and threading in Java. This is the area in which I have the most problem in Java. I learned to do thread programming in our Operating Systems course (EECS 338) in C. Imagine my surprise one evening at 3 AM, the day a project is due, when I find that Java threads cannot signal each other, that something closer to a monitor-based solution is required. That's all well and good if the threads are worker threads that don't interact with each other, but trying to get threads to communicate immediately became (at least in my head) an absolute nightmare. The resulting 4 AM hack is quite likely the most painful bit of programming I have ever had the misfortune to turn in. By passing a single vector into both threads, I was able to create shared memory in the form of a thread-safe object. The program devolved into a semaphore based solution, each thread going into a non-blocking continuous loop until the other thread set a flag announcing that it was finished. This is still a mental shift I need to devote some time to studying before I get hit with the problem again.
During my first internship with Hewlett Packard, when I was picking up the basics of scripting, I ran across a very amusing example of a dedicated Windows batch script writer showing just how powerful the scripting language was. The programmer showed how to create linked lists among other dynamic data structures using the ability to create a large number of temporary files. While it was amazing to witness the extent to which someone could expand such a specific language, I was more interested in tracking the programmer down to inform them that there are actually languages designed for such things that don't cause a cascading number of files to be created, accessed, and subsequently deleted.