|
nuthole.com
"even my henchmen think I'm crazy"
contact: subscribe: 2006 06 |
|
|
2006 06 21 - Wed fram och tillbakaposted by jack at 03:46 CET in / creations
|
| permalink | | digg this | slashdot this | add to del.icio.us | | 0 comments (why don't you write the first?) |
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<Value> 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:
self.append vs push_back)values parameter isn't statically typed, so it doesn't need to actually be a standard python array, but can be any class that implements the methods required for iterationfor 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.
| permalink | | digg this | slashdot this | add to del.icio.us | | 7 comments |