Gillius's Programming

Java and C++

While my strongest programming language now is Java, there was a time long ago where my strongest language and my preferred language was C++. In my educational career and early personal projects, I did a lot of work in C++, but in my professional career I've done mostly Java. Recently I had an opportunity to build a non-trivial program in C++, something I haven't had a chance to do in some years (since GNE). I was surprised at how fast my knowledge came back, it seems that learning a programming language is like learning to ride a bike -- you never quite forget. But through this project, I came to revisit a lot of my opinions. The main one is that over time I ended up underestimating the power of C++ and overestimating the difficulty of building C++ programs compared to managed languages like C#/Java.

While I still feel development is much faster and easier in managed languages, I noticed right away two features I really missed.

Templates

Java is a strongly-typed language, and I've been looking at dynamic languages more recently like Python and Groovy. One of the main benefits of dynamic coding is "duck-typing" and people may think C++ is completely devoid of such a "high-level" feature, but you can achieve a very similar result at compile-time in select portions of your code with C++ templates, without a runtime speed hit from reflective or interpreted languages. C++ templates generate code for each variation of the call based on types given to the calls. So where in Java you are forced to make overloaded methods, in C++ you can do this with a single template function. The one big disadvantage is that C++ templates are typically defined in headers, which exposes code you might want to keep private, but more importantly does not allow the code to be in a library that can be swapped out or upgraded after compilation, a fact that also complicates binary compability between programs and libraries.

//Java - no speed ovehead, memory overhead for unused methods, works only for pre-coded variants
int add( int a, int b ) { return a + b }
float add( float a, float b ) { return a + b }
//.... repeat for double, short, byte, char, ...
//Groovy - big hit to speed, but works for all types with "add" method at runtime or compile-time
def add( def a, def b ) { a + b }
//C++ - fastest but can have high code size penalty, works for all types with "operator+" at compile-time
template <typename T> T add( const T& a, const T& b) { return a + b }

I wonder if it is possible to combine the best of both worlds, a JVM language with templates -- the first time you call a template method it generates the method in Java bytecode, then executes it. This way it is sort of like JIT source generation (which is JIT compiled by modern VMs). You take a big penalty on the first call, but then subsequent calls are as fast as native language like C++, but without the binary compatibility problems.

Pass by reference

Some academics feel that pass by reference semantics makes function calls complicated because you don't know what parameters are "out" parameters. Maybe that's why all Java parameters are passed by value, but that's not consistent with the fact that it's never possible to pass an object's contents by value (the reference to the object is passed by value). Maybe it was to keep the VM and garbage collector simple -- the only "pointers" allowed are those to objects on the heap. Whatever the case, in Java it's a huge pain in the butt if you want to return multiple values to create a wrapper object. While C++ pass-by-reference calls can be confusing compared to C (which requires a *) or C# (which requires ref/out keywords), it allows patterns like cin:

int a,b,c;
cin >> a >> b >> c;

I know it seems trivial, but compare this to the same code in Java:

Scanner sc = new Scanner(System.in);
int a = sc.nextInt();
int b = sc.nextInt();
int c = sc.nextInt();

It doesn't really change things at the end of the day but it just doesn't feel as easy or cool in Java. Plus, with C++ iostreams you can overload operator>> for your custom types so you can "cin" any type of object while Java's Scanner is restricted only to the built-in overloads.

I suppose one lesson to learn from this is that there is no one true "best" language. Java makes many things much easier and on a whole I think is a lot easier to work with just because of its high-quality base library and simplicity. But it also makes some things harder than they need to be.