Dear Monks!

After many years of happily using Perl, lately I have been exposed to hack on a largish C++ project. So, I had to recall everything I have ever known about C++ and STL and to even learn much more new stuff (boy, g++ is really slow these days!)

I decided to read some nice tutorials on STL data structures, but soon I was shocked to realize that, during the many years of using Perl almost exclusively to everything (and only doing really low level stuff with XS and C), I have lost my ability to think in concepts other than Perl's good old arrays and hashes. So I began to search for STL counterparts.

Take for example arrays. The most straightforward STL choice would be vectors. With vectors, the familiar syntax $array[$index] = $element will work in C++ too, search and insert is fast. With C++ automatic variables, I also have the counterpart of Perl lexicals. This is really nice. However, based on my (granted, limited) understanding of STL, with vectors, you must know the size of the array well before starting to use it. Trying to write to the $indexth element of the array before actually initializing it is a pretty straight call for a segfault, as I had the chance to learn through live experience.

After falling into this trap a number of times, I realized that I more and more grow to use STL maps, which do not show this notorious problem. However, the more I used maps the more my programs began to crawl, up to the point that today, my Perl scripts tend to execute faster than the C++ counterparts.

Here is a little snippet (which is a shameless plug of merlyn's implementation to search the first 1 million primes), which remarkably demonstrates this phenomenon:

#include <map> #include <stdio.h> #define our(x) std::map<int,int> x #define my int #define eval int main() #define next continue eval{ my $UPPER = 1000000; our($sieve); for(my $i = 0; $i < $UPPER; $i++){ $sieve[$i] = 0; } for (my $guess = 2; $guess <= $UPPER; $guess++) { if($sieve[$guess]){ next; } for (my $mults = $guess * 2; $mults <= $UPPER; $mults += $guess) { $sieve[$mults] = 1; } } my $count = 0; for(my $i = 2; $i < $UPPER; $i++){ if($sieve[$i] == 0){ $count++; } } printf("The number of primes below %i is %i\n", $UPPER, $count); }
Provided that you name the file as sieve.cpp, you can compile it with g++ -Wall -fdollars-in-identifiers sieve.cpp -o sieve or you can directly feed it into Perl, too (perl sieve.cpp). For clarity, it is currently not strict-safe. If you are interested in multilingual obfu, look at here: Perl is C.

What is pretty interesting here is that the C++ code runs for 14 seconds, while 7 seconds is enough for Perl to give the very same answer. For this specifically CPU intensive problem, Perl's compiled byte-code runs twice as fast as the native machine code generated by C++! Now, this is what I call surprising. My C++-inclined colleagues simply couldn't believe it until not running the code by themselves. Moreover, the higher $UPPER is set, the larger the difference between the Perl code and the C++ code will become. This is why most of my C++ code written so far sucks so very badly...

I was quickly pointed out that this behavior is obviously a consequence of my stupid choice of STL container classes. STL maps are not on par with Perl arrays, even if the syntactical similarity made me blatantly think so. Moreover, in this very special case, the size of the array is known in advance, so I could have very much like used STL vectors as well, instead of maps. Change the

#define our(x) std::map<int,int> x
#include <vector> #define our(x) std::vector<int> x($UPPER)
and now the code is transformed to vectors. Consequently, the execution time of the C++ code drops below 1 second. The consequence seems to be: Choose your STL containers carefully!

Consequently, my question is: are there any other monks here, who caught themselves on trying to force Perlish way of thinking to other programming languages? In what way did you abuse those other programming languages?