Saturday, June 30, 2012

One Good Thing

C++ isn't quite that terrible, in my opinion.

Wait, don't run away!

Yes, I know, the fact that C++ is a bad language is pretty much the biggest consensus in the world of software. It really does have many problems. In fact, to balance my karma I may have to write another post about bad things in C++. But for now, let's maintain a positive attitude.

Everybody knows the standard reason for using C++: it's practically a really fancy assembly language. This seems to be why C++ has been relatively popular for a long time, because there are just too many applications where you need this low level access.
I think C++ also has an advantage in the opposite direction. You can make it look good, almost like a high-level language.

I'm going to give you a few minutes to stop laughing.
Seriously. You can make C++ code look good. I very deliberately didn't say you can do it easily, because it's a lot of overhead work. But this overhead work is possible, which is not a trivial thing at all, and after you've done it, you can have nice customized syntax that could very well fit your needs better than some other languages.

I've often heard of LISP fans saying that the great thing about it (except for the abundance of parentheses) is that macros allow you to invent your own language. But for some reason, C++ programmers consider the idea taboo. It might just be my luck, but most C++ programmers I've met considered it a terrible sin to use macros to create new syntax. In fact, it's often said that it's best not to use macros at all. Nor operator overloading. And coercion is the most dangerous invention since the sharkapult. And templates are fat and ugly. These people, I think, would do well to stick with C, because they wouldn't even notice the difference.

Take, for example, data members.
The implicit scope in C++ member functions can be pretty dangerous, I suppose; you write a variable's name and you don't know if it's an object's data member or global variable or something else. This is, allegedly, a very bad feature in C++, one that should not exist at all. In Python you have to to disambiguate the scope, usually by adding self. and in PHP it's this->. The standard C++ solution is to prefix data members with m_ so they're easily identifiable. Personally I think that any of the above solutions is just fine.

But what if you're writing a little class that just stores a lot of information without doing anything impressive to it? I mean the sort of thing that you write as a struct instead of class. When you write a class that represents a point in 4-dimensional space, with the data members x, y, z, t you probably wouldn't even bother with the m_ prefix because it's such a waste of space... but in Python and PHP you still have to write self and this again and again. That's just making the code much longer than it needs to be while it's doing fairly obvious things.

On the other hand, if it's a more serious case... well, there's nobody stopping you from deciding that your local convention is using this-> in C++ if you decide that it's safer. Prefer the Python way? Great, me too, #define self *this.
Either way, you now have the advantage of another language's standard in your own C++ code.

This is just one of many examples.

Another reason to despise C++ is that strings aren't a native type. The sort of thing you do in half a line in a normal language usually takes 10 lines or so in C++ and involves horrible things like pointers. But there's nobody stopping you from writing your own string class that supports the sort of operations (and, more importantly, operators) you want. Some people might be happy littering their code with thousands of (LPCSTR) and .c_str() and other such abominations, but with a few hours of work and some daring operator overloads you can create a string class that looks as elegant as Python's % operator.
Or you can build something that works like streams without being so maddeningly tedious.
Or you can give all your classes their own functions or operators that make it easy for them to work with streams.
Maybe you can even get a syntax that resembles TCL or PHP by doing creative things with the preprocessor.
The choice is completely yours.

The basic syntax of the for loop is too annoying for you? I agree completely! Let's try something similar to SmallTalk then:
#define timesRepeat(n) for (unsigned i=0; i<n; i++)
And if you want an index in your loop, just replace (n) in the above definition with (i,n).

If you're tired of how troublesome it is to write code that checks for a lot of potential errors, you can take advantage of the lazy evaluation like I've described before. This sort of syntax is apparently standard in Perl, and there's no reason not to use it in C++ where appropriate.

Personally I dislike the way conditions always take up more space than they should. At worst, with lots of pointless braces and newlines, the simplest if/else will take up 8 lines. At the other end of the spectrum you could probably fit it into 2.
In my opinion, since an if/else has 3 elements (condition, true block, false block) then a simple if/else should take up 3 lines. Therefore I want to use this syntax in my new language:

zombieCount>10 ?
    use(RocketLauncher())  &&  broadcast("HELP!!!") :
    use(Shotgun())  &&  broadcast ("help! (not urgent)");

I think you'll agree that for a new language you've never seen before, this is relatively easy to read. Coincidentally, this works in C++.

That's just a few random examples. I suspect you can mimic VB's with syntax with some creative macros. I'm certain you can mimic Python's with even more easily. You can make a convincing foreach with simple macros. You could even use exceptions, though they are the software equivalent of horcruxes and I will not speak of them (lest my impressionable audience turns towards Dark Programming).

I'm not trying to convince anyone to use C++. In fact, I would almost never encourage such a thing.
All I'm saying is that when circumstances force you to use C++, odds are the project is a big one, and if you spend a few days creating infrastructure and coding conventions that fit your needs it will save you a lot of time and make your code better.
Also, don't worry about what other people might think of your strange code; there is no universal standard for C++, and the new guy joining your project can surely get used to the strange code faster than he can learn all the classes and interfaces and design and conventions. If anybody gives your code an odd look just tell them it's a secret new language, and it's the reason your team manages to work so efficiently.

No comments:

Post a Comment