Descending the Programming Tower of Babel
In the last decade as a software engineer I've consistently read that one of the best ways to improve is to learn a new language. Personally, I've found fault with that assertion and have wondered at length why it's so generally agreed upon. In certain cases, like learning functional programming the reward is clear. However, these strike me as special cases that don't generalize well.
Now, I've not shied from the task. On the contrary, I've worked to pick up multiple languages. Regardless of whether or not it makes me better, to a certain extent we're all obligated to keep up to stay relevant. To date, I've viewed this not so much as a matter of improving but one of economic necessity.
Today however, it struck me that there's in fact an order to computer programming language discovery. One that's largely chronological. If you proceed from old to new, the exercise of mastering a new language is essentially one of memorizing a toolbox of shortcuts. Does this make you a better engineer? Perhaps it makes one more efficient, certainly more employable, but better? The progression indeed often comes with the cost of loss of control or visibility into the details of what exactly it is you're doing.
If you were to progress chronologically, you'd be saving time but arguably understanding less. It'd be not unlike the old Twilight Zone episode where a man goes to the future only to find that people speak entirely in acronyms in order to save time. Ordinarily the progression of time is associated with an increase in entropy but in this case it is the opposite. One may even go so far as to say that languages have been moving from imperative to more declarative.
Let's take a simple String Reversal as an example:
C++
int i=0, j; j=strlen(str)-1; while(i<j){ temp=str[i]; str[i]=str[j]; str[j]=temp; i++; j--; }
Here there are no strings, just character arrays. A string is an array in which the end is marked by an unreadable null character, \0. We loop outside in over the characters swapping front and back.
Java
return StringBuilder(str).reverse().toString();
Here we convert from String to StringBuilder, use the latter's reverse() method, convert back to String, and return. Presumably reverse() does something like what the C++ implementation above is doing.The conversion is necessary because the Java String class is immutable. If we ran the C++ swap algorithm using Java Strings, each iteration would require allocation of memory for a new Strings entirely replacing the old ones. This would be inefficient and awkward. A better place for this is StringBuilder class, where in place manipulations on String data should take place.
Why are Strings immutable in Java? That's an interesting subject worth looking into and by doing so we really can start to learn a bit about how the language was designed and why. There are a number of benefits that come with this choice including caching and thread safety.
Python
return str[::-1]
Not unlike Java's reverse(), however even more terse and with no need of converting between types.In going from C++ to Java to Python have I become a better programmer? I've gained about an order of magnitude in keystroke efficiency. In considering the details of why the approach differed, I may have learned a bit about memory management, etc but coming from C++ I really had better have a strong grasp of that already.
Now if we proceed in the opposite direction however, new to old, we can begin to see why learning a "new" language can be so illuminating. We're expanding detail as to what exactly the computer is doing to achieve the string reversal. If I'd never dealt with character arrays and suddenly found out that in C++ I had to loop over the characters every time, I'm pretty sure it would be an "aha" moment.
I've never worked with COBOL or one of the mainframe languages but have played with assembly code. It felt extremely slow and obtuse. However, I found it fascinating that once compiled, all of my C code was executing these simple instructions and how much closer they were to the hardware. This helped break up the cognitive dissonance for me when I was first learning to code. I could directly trace how my code was manipulating physical memory. This built a mental bridge for me from abstract to material.
Considering this, I at last see how learning a new language can be more than just a rote exercise.
https://martinfowler.com/bliki/ValueObject.html
Comments
Post a Comment