huge volumes of pointless syntax

It’s high time for the next installment in my irregular series of C++ rants. This time I’m going to talk about expressiveness (or rather, C++’s lack thereof)


Expressiveness indicates a capability to accurately and briefly express something. A human being is considered to be expressive if they are able to speak in such a way that someone listening to them can quickly understand the person’s message. A computer language’s expressiveness is a measure of how quickly a programmer can write code that is unambiguous and a correct reflection of the design in the programmer’s mind.


Let’s illustrate this with an example. Imagine we’ve got a class with an instance variable containing an array (or list, or vector, or what have you) of some other type. We want to give our class a method that takes another array, iterates through all the objects in it, and adds them to its own array. Obviously this is a contrived example, since nearly all container classes in all languages must include functionality for adding the contents of one array to another, but the point here is to demonstrate how a simple iteration is done.


Let’s start off with the C++ version, something like this:


class ValueContainer
{
    // a vector containing Value objects
    std::vector<boost::shared_ptr<Value> > m_values;

void addValues(std::vector<boost::shared_ptr<Value> >values) { // an iterator pointing at the first value std::vector<boost::shared_ptr<Value> >::const_iterator it = values.begin(); // an iterator pointing at the special “end” value indicating we’ve reached the end std::vector<boost::shared_ptr<Value> >::const_iterator endIt = values.end(); // step through the entire array for (; it != endIt; ++it) { // add the value to our array m_values.push_back(*it); } }

};



Some of you may be unfamiliar with the boost::shared_ptr stuff in there. The boost project is a sort of proving ground for classes that are probably destined for the standard c++ library in the future, and shared pointers are a very valuable concept that make c++ development a little more do-able, by helping you manage object ownership.


Anyway, that’s quite a pile of code, isn’t it? All we’re doing is walking through a list of things!


Some may balk at this, saying that the boost shared pointers are overkill here. OK, fine, let’s take those away, and take away the comments, and stuff all we can into the for, getting this down as tight as we can:


class ValueContainer
{
    std::vector&lt;Value&gt; m_values;

void addValues(std::vector<Value> values) { for (std::vector<Value >::const_iterator it = values.begin(); it != values.end(); ++it) { m_values.push_back(*it); } }

};



Now let’s see how a similar class might look in python:


class ValueContainer:
    def __init__(self):
        self.values = []

def addValues(self, values): for v in values: self.values.append(v)



Unlike C++, Python has no free-standing declarations of instance variables—they’re defined only as they’re referenced inside of methods, and the best practice is typically to provide an initial definition inside the initilializer method __init__ as I’ve done here.


There are several nice things about Python that this highlights:

but the big win I want to point out here is really the difference in the for constructs.


Look at the mass of ugliness in the C++ for construct. To start off with, you’re forced to declare a variable with a bizarre iterator type. Why should I have to care about that? I’m not using it in any way; that type is completely irrelevant to my code. Later, to iterate I have to use it++, which may not be pointer arithmetic, but at least looks like pointer arithmetic, and that is just so 1985.


Then, take a look at the simplicity of the Python for construct. The designers of Python built iteration right into the language! You simply give for the name of the variable that should be used to hold a value from the array, and the array itself, and off it goes. Behind the scenes, iteration occurs through well-defined methods, and if you’re making your own collection class you can define your own iteration scheme, but all of that is completely invisible to a user of the class.


IMHO, this sort of thing is really one of the biggest wins for languages like Python. You get to leave out all sorts of meaningless busy-work, since the language includes useful mechanisms that C-based languages don’t, and you are left with the job of programming the actual functionality you’re after.

Comments